覆盖Java System.currentTimeMillis以测试对时间敏感的代码 [英] Override Java System.currentTimeMillis for testing time sensitive code
问题描述
有没有办法,无论是在代码中还是在JVM参数中,都可以覆盖当前时间,如通过 System.currentTimeMillis
所示,而不是手动更改系统时钟主机?
Is there a way, either in code or with JVM arguments, to override the current time, as presented via System.currentTimeMillis
, other than manually changing the system clock on the host machine?
一点背景:
我们有一个系统可以运行多个会计工作围绕当前日期(即本月的第一天,一年中的第一天等)展开他们的大部分逻辑。
We have a system that runs a number of accounting jobs that revolve much of their logic around the current date (ie 1st of the month, 1st of the year, etc)
不幸的是,许多遗留代码调用了诸如 new Date()
或 Calendar.getInstance()
,两者最终都会调用 System.currentTimeMillis
。
Unfortunately, a lot of the legacy code calls functions such as new Date()
or Calendar.getInstance()
, both of which eventually call down to System.currentTimeMillis
.
出于测试目的,我们现在仍然无法手动更新系统时钟来操纵代码的时间和日期认为测试正在进行。
For testing purposes, right now, we are stuck with manually updating the system clock to manipulate what time and date the code thinks that the test is being run.
所以我的问题是:
有没有办法覆盖什么由 System.currentTimeMillis
返回?例如,告诉JVM在从该方法返回之前自动添加或减去一些偏移量?
Is there a way to override what is returned by System.currentTimeMillis
? For example, to tell the JVM to automatically add or subtract some offset before returning from that method?
提前致谢!
推荐答案
我强烈建议您不要乱用系统时钟,而是重复使用旧版代码以使用可更换的时钟。 理想情况应该通过依赖注入来完成,但即使你使用了可替换的单例,你也会获得可测试性。
I strongly recommend that instead of messing with the system clock, you bite the bullet and refactor that legacy code to use a replaceable clock. Ideally that should be done with dependency injection, but even if you used a replaceable singleton you would gain testability.
这几乎可以通过搜索和替换单例版本:
This could almost be automated with search and replace for the singleton version:
- 替换
Calendar.getInstance()
withClock.getInstance()。getCalendarInstance()
。 - 替换
new Date()
withClock.getInstance()。newDate()
- 替换
System.currentTimeMillis()
withClock.getInstance()。currentTimeMillis()
- Replace
Calendar.getInstance()
withClock.getInstance().getCalendarInstance()
. - Replace
new Date()
withClock.getInstance().newDate()
- Replace
System.currentTimeMillis()
withClock.getInstance().currentTimeMillis()
(根据需要等)
一旦你完成了第一步,你可以一次用DI替换单身。
Once you've taken that first step, you can replace the singleton with DI a bit at a time.
这篇关于覆盖Java System.currentTimeMillis以测试对时间敏感的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!