【问题标题】:Is it safe to use DateTimeUtils.setCurrentMillisFixed in tests?在测试中使用 DateTimeUtils.setCurrentMillisFixed 是否安全?
【发布时间】:2014-01-23 19:40:27
【问题描述】:

为了测试与时间相关的代码,最好使用Virtual Clock Pattern

我们的想法是,我们不使用new Date,而是从一个时钟中提取当前时间,该时钟可以使用返回预定义固定时间的虚拟时钟进行模拟。

现在在 Java 中,我们有带有 DateTime 类的 JodaTime,它允许使用

设置采样时间
DateTimeUtils.setCurrentMillisFixed(today.getMillis());

并将固定时间重置为系统时间:

DateTimeUtils.setCurrentMillisSystem();

这是一个good article,介绍如何将它与 TestNG 一起使用。

现在是问题!

如果在全局上下文中为运行测试的时间全局设置固定时间,那么将此技术与 setUp 和 tearDown 方法一起使用是多么安全。只要我明白了——它只有在我们没有两个并发测试的情况下才能工作,并且这种技术在同一环境中并行运行。

【问题讨论】:

  • 如果你使用threeten(successor of jodatime)或者java 8,有一个内置的Clock class for that purpose
  • 正如您所说,并行运行测试不会可靠地工作。如果测试按顺序运行并按照您提到自己的方式装饰测试,这是非常安全的。

标签: java junit testng jodatime


【解决方案1】:

您必须确保在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 类,所以它知道(目前)不存在其他实现。在这种假设下,它可以只使用内联方法。

所以我更喜欢以最容易测试的方式编写代码。

编辑

对于 Java 8,您可能希望使用 Supplier<Long> 接口。

例如在您的客户端代码中,您可以使用 method references

public class SomeClass {
    private Supplier<Long> currentTimeMillisSupplier;

    public SomeClass(){
         this(System::currentTimeMillis);
    }

    SomeClass(Supplier<Long> currentTimeMillisSupplier){
        this.currentTimeMillisSupplier = currentTimeMillisSupplier;
    }
}

默认构造函数用于“正常”使用,而其他包作用域构造函数可用于单元测试。只需将测试类放在同一个包中即可。

你也可以使用Clock接口,因为它是一个@FunctionalInterface

public class SomeClass {
    private Clock clock;

    public SomeClass(){
         this(System::currentTimeMillis);
    }

    public SomeClass(Clock clock){
        this.clock = clock;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-06
    • 2014-03-07
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    相关资源
    最近更新 更多