В Grails, есть ли хороший способ высмеивать текущее время, используя время Joda? - PullRequest
8 голосов
/ 26 мая 2011

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

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

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

Ответы [ 3 ]

18 голосов
/ 26 мая 2011

Я знаю, что это уже принято, но с Joda-time вы можете замерзнуть и установить его так, как вам нравится.Таким образом, вы можете заморозить время, опередить время, вернуться назад во времени.При условии, что вы используете 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();
5 голосов
/ 26 мая 2011

В итоге мы создали dateService методом now().В модульных тестах мы имитируем его с помощью

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

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

Модульные тесты, OTOH, выглядят довольно ясно с этим.*

2 голосов
/ 26 мая 2011

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

  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)
    }
}
...