Robolectric 3.0:模拟System.currentTimeMillis()

Mar*_*ark 5 android unit-testing robolectric

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

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

ShadowSystemClock shadowClock = Robolectric.shadowOf(SystemClock.class);
shadowClock.setCurrentTimeMillis(1424369871446);
Run Code Online (Sandbox Code Playgroud)

自shadowOf方法被删除后不编译.尝试替代方案,如:

ShadowSystemClock shadowClock = new ShadowSystemClock();
shadowClock.setCurrentTimeMillis(1424369871446);
Run Code Online (Sandbox Code Playgroud)

看来有覆盖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());
Run Code Online (Sandbox Code Playgroud)

输出:

system = 1438212006879; shadow = 0; time from code = 1438212006894
system = 1438212006898; shadow = 50000000; time from code = 1438212006898
Run Code Online (Sandbox Code Playgroud)

Code.getSystemTime()正在调用正在测试的代码库.该方法只返回System.currentTimeMillis().

看起来如果ShadowSystemClock拦截了对currentTimeMillis()的调用,事情就可以工作了.有没有办法做到这一点?

Fr *_*ieg 9

首先,因为SystemClock是一个完全由静态方法组成的单例类,所以不需要使用shadowOf().shadowOf()仅用于查找对象实例的阴影.要访问阴影静态方法SystemClock,只需直接调用静态方法,ShadowSystemClock就不必ShadowSystemClock通过调用实例化new.在你的测试代码,你应该能够调用分配new和repace shadowClock.currentTimeMillis()ShadowSystemClock.currentTimeMillis().

其次,与你关于System.currentTimeMillis()截获的问题更直接相关- 在Robolectric下,这将发生,但仅适用于已经检测的代码- 也就是说,由Robolectric的特殊类加载器加载修改.在检测代码中,所有呼叫System.currentTimeMillis()都被呼叫替换ShadowSystemClock.currentTimeMillis(),这就是您想要的.

因此,为了使测试按照您希望的方式工作,您需要确保测试的代码已经过检测.默认情况下,Robolectric不会对所有类执行此操作 - 仅限Android类.不幸的是,我现在无法为自己测试这个,但我相信你可以告诉Robolectric通过在@Config注释中指定包来测试你自己的应用程序类 - 例如,如果你把@Config(instrumentedPackages={ "my.application" })在你的测试类或方法上,然后告诉Robolectric来检测"my.application"包中的所有类.这将导致他们的System.currentTimeMillis()调用被重定向到ShadowSystemClock.currentTimeMillis(),这应该是你想要的.

这是做不同的原因是因为使用Robolectric的类加载器方法,它是不可能修改的类java.lang.*,因为它们已经加载,然后才能安装插装的类加载器包.使用类似于JMockit的方法尝试在Robolectric中以不同方式执行此操作有一个长期的想法,这可以解决这个问题.这意味着您不必明确地检测所有客户端类.然而,目前这是天上掉馅饼,我不会屏住呼吸等待它 - 希望上面的内容能解决你眼前的问题.

希望这可以帮助.


Baj*_*jji -1

你需要使用Shadows.shadowOf()