我正在尝试修改System.currentTimeMillis()返回的值,因此我可以执行以下操作:向数据库中写入内容,模拟等待5分钟,对数据库进行查询(查询取决于写入值的时间) )。

[此SO线程]中建议的代码:

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。在测试代​​码中,您应该可以免除对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/

10-09 03:06