gpt4 book ai didi

java - 在测试中使用 DateTimeUtils.setCurrentMillisFixed 是否安全?

转载 作者:IT老高 更新时间:2023-10-28 21:01:38 25 4
gpt4 key购买 nike

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

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

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

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

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

DateTimeUtils.setCurrentMillisSystem();

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

现在是问题!

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

最佳答案

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

当我想将一个类与 System.currentTimeMillis(); 解耦时,我通常更喜欢另一种方式。 .介绍接口(interface)Clock和一种实现SystemClock像这样:

public interface Clock {
public long getCurrentTimeMillis();
}

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

对于测试,很容易创建一个模拟,它要么在每次调用时返回固定时间,要么返回一系列预定义的时间。

有些人可能会争辩说,引入这样的接口(interface)以仅解耦一种方法是过度工程化,并且会影响性​​能。但幸运的是,我们有一个 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接口(interface),因为它是一个 @FunctionalInterface .

public class SomeClass {
private Clock clock;

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

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

关于java - 在测试中使用 DateTimeUtils.setCurrentMillisFixed 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20949337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com