2011-05-25 2 views
8

Я пишу код, который выполняет расчеты даты и времени с текущим временем. Во время Joda это достигается через конструктор (Java), поскольку он является неизменным объектом. Мне нужно уметь издеваться над тем, чтобы возвращал определенный постоянный момент, чтобы я мог делать разумные утверждения теста, но оставлять все остальные методы DateTime.В Grails, есть ли хороший способ высмеять текущее время, используя время Joda?

Это доказывает неприятность. Grails mockFor(DateTime, true) не позволит мне высмеять Java-конструктор, но нет очевидного или читаемого неструктурированного способа получить время в Joda.

Доступные опции, похоже, включают в себя низкоуровневые JVM-методы, такие как JMockit или класс EasyMock 3 класса, которые являются болью от Grails. Есть ли простой/простой способ достичь этого?

ответ

5

Мы в конечном итоге создание dateService с now() методом. В единичных тестах мы дразнить его с

domainInstance.dateService = [ now: { currentTime } ] as DateService 

где currentTime является поле модульного тестирования класса. Это накладывает зависимость каждого на dateService (наша единственная почти глобальная зависимость), а для классов src нужно передать ее вручную.

Единичные тесты, OTOH, выглядят довольно четко.

+0

Отличный ответ. Я как-то надеялся избежать архитектуры системы по-разному, чтобы сделать этот тест возможным, но я многому научился о том, насколько болезненно это может быть издевка над конструкторами. –

+0

Спасибо. Я стараюсь избегать прямого вызова конструктора - он нарушает «код для интерфейса», созданный экземпляр не может быть экстернализирован, как в тестах, а иногда приводит к «Construction Blobs». Таким образом, это сводилось к форме инъекции зависимости. –

2

Вы могли бы просто использовать добрые старомодные принципы OO, например.

interface TimeService { 
    DateTime getCurrentTime() 

    // other time-related methods 
    } 

    class JodaTimeService implements TimeService { 
    DateTime getCurrentTime() { 
     new DateTime() 
    } 
    } 

    class MockTimeService implements TimeService { 
    DateTime getCurrentTime() { 
     // return a fixed point in time 
    } 
    } 

Ваш код должен получить ссылку на реализацию TimeService через инъекции зависимостей. В resources.groovy использовать MockTimeService только при выполнении тестов

import grails.util.Environment 

beans = {  
    if (Environment.current == Environment.TEST) { 
     timeService(MockTimeService) 

    } else { 
     timeService(JodaTimeService) 
    } 
} 
+0

Независимо от того же подхода, что и выше, большое спасибо и хорошее решение, проработанное по глубине. И дополнительная благодарность за подсказки об использовании тестовой среды для переключения. –

18

Я знаю, что это уже принято, но с Йодой-временем вы можете замерзнуть и настроить его как угодно. Таким образом, вы можете заморозить время, увеличить время, вернуться вовремя. При условии, что вы используете Joda последовательно, ваши объекты получат «сейчас» как любое время, которое вы установили.

// Stop time (and set a particular point in time): 
DateTimeUtils.setCurrentMillisFixed(whenever); 

// Advance time by the offset: 
DateTimeUtils.setCurrentMillisOffset(offsetFromCurrent); 

// Restore time (you could do this in an @After method) 
DateTimeUtils.setCurrentMillisSystem(); 
+0

Oooh опрятный, я надеялся на что-то подобное. Это упростит тестирование. Отличный совет !! –

+0

Теперь я чувствую себя глупо, потому что мы на Джоде. Это лучший способ. Хорошо, я кое-что узнал. –

Смежные вопросы