2014-01-06 54 views
14

为了测试时间相关的代码这是很好的使用Virtual Clock Pattern在测试中使用DateTimeUtils.setCurrentMillisFixed安全吗?

的想法是,我们拉当前时间不使用new Date,但可与虚拟时钟返回预定的固定时间被嘲笑的时钟。

现在,在Java中,我们有JodaTime与DateTime类和允许设置的采样时间与

DateTimeUtils.setCurrentMillisFixed(today.getMillis()); 

和固定时间重置为系统时间:

DateTimeUtils.setCurrentMillisSystem(); 

这里是一个good article关于如何将它与TestNG一起使用。

现在的问题!

如果在全局上下文中为运行测试时间设置全局上下文中的固定时间,那么将此技术与setUp和tearDown方法一起使用有多安全。只要我得到它 - 只要我们没有两个并行测试,并行运行在相同环境中的这种技术,它就会工作。

+3

如果您使用threeten([jodatime的后继](http://stackoverflow.com/a/4633326/829571))或java 8,则有一个内置的['Clock'类用于此目的](http ://download.java.net/jdk8/docs/api/java/time/Clock.html) – assylias

+0

正如您所说的,并行运行测试并不可靠。如果测试按顺序运行并按照您提到的方式修改测试,则这非常安全。 – skirsch

回答

12

您必须确保在tearDown方法中调用DateTimeUtils.setCurrentMillisSystem()。所以一个测试不会影响另一个。即使您的测试发生异常,TestNG也应该调用tearDown

我经常更喜欢另一种方式,当我想从System.currentTimeMillis();分离一个类。我介绍一个接口Clock和一个实现SystemClock这样的:

public interface Clock { 
    public long getCurrentTimeMillis(); 
} 

public class SystemClock implements Clock { 
    public long getCurrentTimeMillis(){ 
     return System.currentTimeMillis(); 
    } 
} 

因为这是那么容易创建一个模拟,要么返回每次调用或一系列预定义的时间固定时间的考验。

有些人可能会争辩说,引入这样一个接口来解耦只有一种方法是过度工程,并且这会影响性能。但幸运的是,我们有一个JIT编译器,因为JIT知道只有SystemClock类被加载,所以它知道没有其他实现存在(此刻)。在这个假设下,它可以使用内联方法。

所以我更愿意以最好的方式编写代码。