首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Robolectric 3.0:模拟System.currentTimeMillis()

Robolectric 3.0:模拟System.currentTimeMillis()
EN

Stack Overflow用户
提问于 2015-07-27 17:42:55
回答 2查看 4.3K关注 0票数 6

我试图修改System.currentTimeMillis()返回的值,这样我就可以执行如下操作:向数据库写入一些东西,模拟等待5分钟,对数据库执行查询(查询取决于写入值的时间)。

在这个SO线程中建议的代码

代码语言:javascript
运行
复制
ShadowSystemClock shadowClock = Robolectric.shadowOf(SystemClock.class);
shadowClock.setCurrentTimeMillis(1424369871446);

因为删除了shadowOf方法,所以不会编译。尝试其他办法,例如:

代码语言:javascript
运行
复制
ShadowSystemClock shadowClock = new ShadowSystemClock();
shadowClock.setCurrentTimeMillis(1424369871446);

虽然出现了覆盖currentTimeMillis()的问题,但这些问题应该在3.0版时解决。

我可以将PowerMock添加到我的项目中,并在本例中使用它,但如果这可以用Robolectric实现,我更愿意这样做。

更新:越来越近,但可能遗漏了什么。此代码:

代码语言:javascript
运行
复制
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());

产出如下:

代码语言:javascript
运行
复制
system = 1438212006879; shadow = 0; time from code = 1438212006894
system = 1438212006898; shadow = 50000000; time from code = 1438212006898

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

如果ShadowSystemClock拦截了对currentTimeMillis()的调用,一切似乎都会正常进行。有办法吗?

EN

回答 2

Stack Overflow用户

发布于 2016-03-18 06:56:24

首先,由于SystemClock是一个完全由静态方法组成的单例类,因此不需要使用shadowOf()shadowOf()仅用于查找对象实例的阴影。要访问SystemClock的影子静态方法,只需直接调用ShadowSystemClock的静态方法,而不必通过调用new实例化ShadowSystemClock。在您的测试代码中,您应该能够免除对new的调用,并使用ShadowSystemClock.currentTimeMillis()重新部署shadowClock.currentTimeMillis()

第二,更直接地与您有关System.currentTimeMillis()被拦截的问题有关--在Robolectric下,这将发生,但只对已被检测的代码发生--也就是说,在被Robolectric的特殊类加载器加载时对其进行了修改。在插装代码中,所有对System.currentTimeMillis()的调用都被调用ShadowSystemClock.currentTimeMillis()所取代,这正是您想要的。

因此,为了使您的测试以您想要的方式工作,您需要确保您正在测试的代码是被检测的。默认情况下,不是所有类都是这样的,只有Android类。不幸的是,目前我无法亲自测试这一点,但我相信您可以通过在@Config注释中指定包来测试您自己的应用程序类--例如,如果您将@Config(instrumentedPackages={ "my.application" })放在测试类或方法上,那么这将告诉Robolectric测试"my.application“包中的所有类。这反过来会导致他们的System.currentTimeMillis()调用被重定向到ShadowSystemClock.currentTimeMillis(),这应该是您想要的。

之所以这样做的原因不同,是因为使用Robolectric的类加载器方法,不可能修改java.lang.*包中的类,因为在安装检测类加载器之前已经加载了它们。有一个长期的想法,尝试用类似于JMockit的方法,在Robolectric中以不同的方式来实现这一点,这样就可以解决这个问题。这意味着您不必显式地检测所有客户端类。然而,现在这是空中楼阁,我不会屏住呼吸等待它--希望上面的这些能解决你眼前的问题。

希望这能有所帮助。

票数 13
EN

Stack Overflow用户

发布于 2015-07-27 17:52:14

您需要使用Shadows.shadowOf()

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31659771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档