在Grails中,有一种使用Joda时间模拟当前时间的好方法吗?

时间:2011-05-25 20:56:14

标签: grails time groovy mocking jodatime

我正在编写一些针对当前时间进行日期和时间计算的代码。在Joda时间,这是通过(Java)构造函数访问的,因为它是一个不可变对象。我需要能够进行模拟,以便new DateTime()返回一个特定的常量瞬间,这样我就可以做出合理的测试断言,但只留下所有其他DateTime方法。

这证明是令人讨厌的。 Grails mockFor(DateTime, true)不会让我模拟Java构造函数,但是没有明显或可读的非构造方法来获取Joda时间。

唯一可用的选项似乎涉及低级JVM技术,如JMockit或EasyMock 3类模拟,这是Grails的痛苦。有没有简单/直接的方法来实现这一目标?

3 个答案:

答案 0 :(得分:18)

我知道这已经被接受了,但是在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();

答案 1 :(得分:5)

我们最终使用dateService方法创建now()。在单元测试中,我们用

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

其中currentTime是单元测试类字段。这强加了每个人对dateService(我们唯一的近全局依赖)的依赖,对于src类,必须手动传递它。

单元测试,OTOH,看起来很清楚。

答案 2 :(得分: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)
    }
}