是否可以冻结System.currentTimeMillis()进行测试

use*_*098 10 java testing

出于某些测试目的,我想准确预测System.currentTimeMillis()将返回什么.有什么方法可以冻结或手动设置System.currentTimeMillis()调用时会返回什么?

Jon*_*eet 23

我强烈建议您避免在通用代码中使用System.currentTimeMillis(和new Date()等).

相反,创建一个Clock代表"的服务给你当前时间",然后创建一个实现该接口使用System.currentTimeMillis或什么的,和一个假的实现,你可以明确控制.

使用依赖注入使该服务的实例可用于需要它的代码.在生产中,使用该System.currentTimeMillis版本,并在测试中使用您的假货.

这使您不仅能够停止时间,而且能够将其设置为您想要的任何内容 - 因此您可以拥有您知道永远不会过期的静态测试数据,并且您可以轻松地测试边界周围的棘手事物等.我已经使用了这个在许多项目中非常成功,在我的Noda Time项目中就是这样在"当前时间"得到的方式.

请注意,如果您正在使用Java进行大量时间,我建议您使用Joda Time,并使您的Clock界面返回Instant:

public interface Clock {
    Instant now();
}
Run Code Online (Sandbox Code Playgroud)

  • 在相关的说明:我真的很期待[`java.time`](http://download.java.net/jdk8/docs/api/java/time/package-summary.html)(又名[JSR] -310](http://jcp.org/en/jsr/detail?id=310))最终到达Java 8. (4认同)

mik*_*łak 18

是的,这是可能的,但这是一个测试代码的味道.

您可以使用模拟库来模拟静态方法(如此PowerMock示例中所示),但您应该避免这样做,并将时间数据封装为其他答案所示.

这是测试的样子,使用PowerMockMockito:

@RunWith(PowerMockRunner.class)
@PrepareForTest(System.class)
public class TestTime {

    @Test
    public void testTime() {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.currentTimeMillis()).thenReturn(42l);
        System.out.println(System.currentTimeMillis()); //prints 42

        //your test code here
    }

}
Run Code Online (Sandbox Code Playgroud)

  • @PeterLawrey:不,那是一个小写的"L",而不是"1". (4认同)
  • :d.我*真的*应该最终重新训练自己使用`L`代替.哦,我们称之为代码阅读技能培训奖金. (2认同)

mor*_*ano 2

是否可以冻结 System.currentTimeMillis()?

如果您希望代码能够被测试,您需要在该时间值周围使用某种包装器