Java 是否可以冻结System.currentTimeMillis()进行测试
出于某些测试目的,我想准确预测Java 是否可以冻结System.currentTimeMillis()进行测试,java,testing,Java,Testing,出于某些测试目的,我想准确预测System.currentTimeMillis()将返回什么。当调用System.currentTimeMillis()时,是否有任何方法可以冻结或手动设置将返回的内容?是否可以冻结System.currentTimeMillis()否 如果希望代码能够被测试,则需要在该时间值周围使用某种包装器。不,不能设置或冻结。 但是如果您的要求是这样的,那么在这种情况下,您可以在变量中设置时间,并在需要时使用。但是System.currentTimeMills()将始终以毫
System.currentTimeMillis()
将返回什么。当调用System.currentTimeMillis()
时,是否有任何方法可以冻结或手动设置将返回的内容?是否可以冻结System.currentTimeMillis()否
如果希望代码能够被测试,则需要在该时间值周围使用某种包装器。不,不能设置或冻结。
但是如果您的要求是这样的,那么在这种情况下,您可以在变量中设置时间,并在需要时使用。但是System.currentTimeMills()将始终以毫秒为单位返回当前时间值。我强烈建议您避免使用
System.currentTimeMillis
(和新日期()
等)在您的通用代码中
相反,创建一个表示“为您提供当前时间的服务”的Clock
接口,然后创建一个使用System.currentTimeMillis
或任何东西的实现,以及一个可以显式控制的伪实现
使用依赖项注入使此服务的实例可供需要它的代码使用。在生产中,使用System.currentTimeMillis
版本,在测试中使用假冒产品
这不仅使您能够停止时间,而且可以将其设置为您想要的任何值-这样您就可以拥有静态测试数据,您知道这些数据永远不会过期,并且您可以轻松地测试边界周围的棘手问题等。我在许多项目中非常成功地使用了这种方法,以至于在我的野田佳彦时间项目中,这是一种获得成功的方法“当前时间”
请注意,如果您正在用Java进行大量的时间工作,我建议您使用并使时钟
接口返回一个即时
:
public interface Clock {
Instant now();
}
是的,这是可能的,但这是测试代码的味道。 您可以使用模拟库来模拟静态方法(如下所示),但是您应该避免这样做,并按照其他答案的建议封装时间数据 这是使用PowerMock和Mockito进行测试的结果:
是,解决方案存在: 例如,出于测试目的,您可以创建自己的包装器系统
package my.pack;
import java.io.PrintStream;
public class System
{
// reuse standard System.out:
public static PrintStream out = java.lang.System.out;
// do anything with chosen method
public static long currentTimeMillis()
{
return 1234567;
}
}
并将其导入到要测试的类中
import my.pack.System;
在这种情况下,对系统的所有调用都将通过您自己的系统类传递
注意:
- 这是“如何拦截System.currentTimeMillis()的解决方案”
- 这不适用于自动测试
- 这不是“如何设计一个好的程序”的一个例子。如果你要求一个好的设计,那么你需要重构你的代码,替换System.currentTimeMillis()-见其他答案
L
,不是1
:D。我真的应该重新训练自己,改用L
。哦,好吧,让我们称之为代码读取技能培训奖金。你真的可以模仿这种方法吗?我很惊讶!您可以使用PowerMock模拟大多数方法(不确定native
)。当然,这并不意味着您应该这样做,除非您处理的是遗留代码怪物或类似的东西。您是否建议仅在测试期间修改被测试类的源代码?这意味着您测试的有效类不是您在生产环境中实际运行的类!是的,您需要修改类以进行测试(附加一行),是的,对于生产,您需要删除该导入。但是,是的,你可以改变行为,这是一个简单的方法除了测试一个不同于你正在部署的类的问题之外,我还认为“简单”的方法:以一种理智的方式自动化它会是一种痛苦,但是,当然,这个解决方案不适用于自动测试。我所说的“简单”是指更少的重构:您不需要使用currentTimeMillis()更改所有行,无论它们在哪里
import my.pack.System;