一尘不染

覆盖Java System.currentTimeMillis以测试对时间敏感的代码

java

System.currentTimeMillis除了在主机上手动更改系统时钟之外,是否可以通过代码或JVM参数覆盖通过呈现的当前时间?

一点背景:

我们有一个系统,该系统运行许多会计工作,这些工作围绕其当前日期(例如,每月的1号,每年的1号等)进行逻辑转换。

不幸的是,许多传统代码都调用诸如new Date()或的函数Calendar.getInstance(),而这两个函数最终都调用到System.currentTimeMillis

出于测试目的,现在,我们不得不手动更新系统时钟,以操纵代码认为正在运行测试的时间和日期。

所以我的问题是:

有没有办法覆盖返回的内容System.currentTimeMillis?例如,要告诉JVM在从该方法返回之前自动添加或减去一些偏移量?

提前致谢!


阅读 283

收藏
2020-03-19

共1个答案

一尘不染

我强烈建议你不要硬着头皮,而是要硬着头皮,重构该旧代码以使用可替换的时钟。理想情况下,应该使用依赖项注入来完成,但是即使你使用了可替换的单例,你也将获得可测试性。

这几乎可以通过搜索自动实现,并替换为单例版本:

  • 替换Calendar.getInstance()为Clock.getInstance().getCalendarInstance()。
  • 替换new Date()为Clock.getInstance().newDate()
  • 替换System.currentTimeMillis()为Clock.getInstance().currentTimeMillis()
    (如需要)

迈出第一步后,你可以一次用DI替换单例。

2020-03-19