【问题标题】:Mocking CountDownTimer and Handler模拟 CountDownTimer 和 Handler
【发布时间】:2016-09-29 15:28:20
【问题描述】:
我正在使用 Mockito 和 PowerMockito 在 Android 上编写我的单元测试。
我已经设法处理几乎所有的东西,但我坚持使用CountDownTimer 和Handler。
我可以模拟CountDownTimer 的子类,但我不能模拟它的final 方法,比如cancel(),所以每次调用cancel() 方法时,测试运行者报告java.lang.RuntimeException: Method cancel in android.os.CountDownTimer not mocked. See ...
有没有人能在不使用 Robolectric 的情况下解决这个问题?
【问题讨论】:
标签:
java
android
unit-testing
mockito
powermockito
【解决方案1】:
这看起来可能是您的编译结构或测试设置有问题。 在问题中发布有关编译设置和测试代码的更多详细信息可能会对您有所帮助。
因为您得到的是“方法...未模拟”,所以您显然已经在使用 Android 提供的一个模拟友好的测试库。 Android SDK 的最新版本包括这个mockable Android jar,首先包含在 Android Studio 和 Android gradle 工具链中;有了这个,所有的实现都是可模拟的,所以你不应该需要 Robolectric 甚至 PowerMockito 来继续前进。
在运行时,将针对 android.jar 的修改版本执行测试,其中所有 final 修饰符已被剥离。这让您可以使用流行的模拟库,例如 Mockito。
但是,由于 javac 可以使用静态调度(即非动态或虚拟)编译对静态和最终方法的调用,如果您编译任何中间工件或库,您可能会发现自己无法利用这个 final-free 库针对确实包含final修饰符的android.jar版本。如果你调用了字节码中的最后一个方法,那么你唯一剩下的选择就是像 Robolectric 和 PowerMock 那样截取或重写字节码。 PowerMock 及其 PrepareForTest 注释可能很难正确处理,因此,如果您尝试过失败,您可能需要在此处发布您的代码以进行查看。
当然,您仍需负责确保您的被测系统使用新提供的模拟; PowerMock 可以拦截对构造函数的调用,并且 Robolectric 用自己的替代方法替换了整个 Android 类,但是对于纯模拟,您需要以一种或另一种方式注入该依赖项。
【解决方案2】:
将此行添加到模块build.gradle
android {
...
testOptions {
unitTests.returnDefaultValues = true
} }