我正在尝试修改 System.currentTimeMillis() 返回的值,以便我可以执行以下操作:向数据库写入内容,模拟等待 5 分钟,对数据库进行查询(查询取决于写入值)。
[this SO thread] 中建议的代码:
ShadowSystemClock shadowClock = Robolectric.shadowOf(SystemClock.class);
shadowClock.setCurrentTimeMillis(1424369871446);
不编译,因为 shadowOf 方法被移除。尝试替代方案,例如:
ShadowSystemClock shadowClock = new ShadowSystemClock();
shadowClock.setCurrentTimeMillis(1424369871446);
似乎有 issues with overriding currentTimeMillis()但这些问题应该从 3.0 版开始修复。
我可以添加 PowerMock到我的项目并将其用于我认为的这种情况,但如果 Robolectric 可以做到这一点,我更愿意这样做。
更新:越来越近了,但可能遗漏了一些东西。这段代码:
ShadowSystemClock shadowClock = new ShadowSystemClock();
Log("system = " + System.currentTimeMillis() + "; shadow = " + shadowClock.currentTimeMillis() + "; time from code = " + Code.getSystemTime());
shadowClock.setCurrentTimeMillis(50000000L);
Log("system = " + System.currentTimeMillis() + "; shadow = " + shadowClock.currentTimeMillis() + "; time from code = " + Code.getSystemTime());
输出这个:
system = 1438212006879; shadow = 0; time from code = 1438212006894
system = 1438212006898; shadow = 50000000; time from code = 1438212006898
Code.getSystemTime() 正在调用正在测试的代码库。该方法仅返回 System.currentTimeMillis()。
如果 ShadowSystemClock 拦截了对 currentTimeMillis() 的调用,似乎一切都可以正常工作。有办法吗?
最佳答案
首先,因为 SystemClock
是一个完全由静态方法组成的单例类,所以不需要使用 shadowOf()
。 shadowOf()
仅在查找对象实例 的阴影时需要。要访问 SystemClock
的影子静态方法,您只需直接调用 ShadowSystemClock
的静态方法,您永远不必通过调用实例化 ShadowSystemClock
新
。在您的测试代码中,您应该能够免除对 new
的调用并将 shadowClock.currentTimeMillis()
替换为 ShadowSystemClock.currentTimeMillis()
.
其次,更直接地与您关于 System.currentTimeMillis()
被拦截的问题相关 - 在 Robolectric 下,这将发生,但仅适用于已被检测的代码 -也就是说,在由 Robolectric 的特殊类加载器加载时进行修改。在检测代码中,所有对 System.currentTimeMillis()
的调用都替换为调用 ShadowSystemClock.currentTimeMillis()
,这就是您想要的。
因此,为了让您的测试按您希望的方式工作,您需要确保您正在测试的代码已被检测。默认情况下,Robolectric 不会对所有类执行此操作 - 仅适用于 Android 类。不幸的是,我目前无法亲自测试,但我相信您可以通过在 @Config 注释中指定包来告诉 Robolectric 检测您自己的应用程序类 - 例如,如果您将@Config(instrumentedPackages={ "my.application"})
在您的测试类或方法上,然后告诉 Robolectric 检测“my.application”包中的所有类。这将反过来导致他们的 System.currentTimeMillis()
调用重定向到 ShadowSystemClock.currentTimeMillis()
,这应该是您想要的。
这样做不同的原因是因为使用 Robolectric 的类加载器方法,无法修改 java.lang.*
包中的类,因为它们在您安装检测类加载器之前已经加载.有一个更长期的想法,即使用类似于 JMockit 所做的方法在 Robolectric 中尝试以不同方式执行此操作,这可以解决此问题。这意味着您不必显式检测所有客户端类。然而,目前这是天上掉馅饼,我不会屏住呼吸等待它 - 希望以上内容能解决您眼前的问题。
希望这对您有所帮助。
关于android - Robolectric 3.0 : Mocking System. currentTimeMillis(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31659771/