我正在编写一些针对当前时间进行日期和时间计算的代码。在Joda时间,这是通过(Java)构造函数访问的,因为它是一个不可变对象。我需要能够进行模拟,以便new DateTime()
返回一个特定的常量瞬间,这样我就可以做出合理的测试断言,但只留下所有其他DateTime方法。
这证明是令人讨厌的。 Grails mockFor(DateTime, true)
不会让我模拟Java构造函数,但是没有明显或可读的非构造方法来获取Joda时间。
唯一可用的选项似乎涉及低级JVM技术,如JMockit或EasyMock 3类模拟,这是Grails的痛苦。有没有简单/直接的方法来实现这一目标?
答案 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)
}
}