如何结合 PowerMock 和 Robolectric

How to combine PowerMock and Robolectric

我有一个使用上下文检查互联网状态的静态方法。所以要模拟它,我需要使用 PowerMock。我正在使用 robolectric 来加快我的测试,因为我唯一需要模拟的就是模拟。但我似乎无法配置 PowerMock(1.6.6) 和 Robolectric(3.2.2) 一起工作。这就是我注释 class:

的方式
@RunWith(RobolectricTestRunner.class)
@org.robolectric.annotation.Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest({Utils.class})

设置方法中的这一行:

PowerMockito.mockStatic(Utils.class);

但是我收到了这个异常:

org.powermock.api.mockito.ClassNotPreparedException: 
The class com.zeyad.usecases.data.utils.Utils not prepared for test.
To prepare this class, add class to the '@PrepareForTest' annotation.
In case if you don't use this annotation, add the annotation on class or  method level. 

at org.powermock.api.mockito.expectation.reporter.MockitoPowerMockReporter.classNotPrepared(MockitoPowerMockReporter.java:32)
at org.powermock.api.mockito.internal.mockcreation.MockTypeValidatorFactory$DefaultMockTypeValidator.validate(MockTypeValidatorFactory.java:38)
at org.powermock.api.mockito.internal.mockcreation.AbstractMockCreator.validateType(AbstractMockCreator.java:10)
at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.createMock(DefaultMockCreator.java:56)
at org.powermock.api.mockito.internal.mockcreation.DefaultMockCreator.mock(DefaultMockCreator.java:46)
at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:71)
at com.zeyad.usecases.data.repository.stores.DataStoreFactoryJUnitTest.setUp(DataStoreFactoryJUnitTest.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:339)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:259)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:41)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:199)

我的 build.gradle 文件依赖项:

testCompile "junit:junit:$junit"
testCompile "org.hamcrest:hamcrest-library:$hamcrest"
testCompile "com.android.support:support-annotations:$supportLibraryVersion"
testCompile "org.mockito:mockito-core:1.10.19"
testCompile "org.robolectric:robolectric:$robolectric"
testCompile "org.robolectric:shadows-support-v4:$robolectric"
testCompile "org.powermock:powermock-module-junit4:$powerMock"
testCompile "org.powermock:powermock-module-junit4-rule:$powerMock"
testCompile "org.powermock:powermock-api-mockito:$powerMock"
testCompile "org.powermock:powermock-classloading-xstream:$powerMock"

有时答案是简单地退后一步,查看您的 "need" 以使用 PowerMock。

所以,您有一个 static 方法需要 PowerMock 是可测试的?!

然后,只需避免使该代码静态。然后,您就不需要使用 PowerMock 了。

简单地用一个接口的组合替换它,impl class(如果你需要 "exactly" 它的一个实现,可能还有一个枚举单例)。

我向你保证:不需要 PowerMock 是更好的选择;与花费很多时间让它与另一个 ByteCode-manipulating 框架一起工作相比。

或者换句话说:学习如何编写 可测试 代码,并做到这一点;而不是创建 hard-to-test 代码,这需要大的 PowerMock 锤子才能变得可测试。观看这些 videos 以了解如何做到这一点。

我不是 RoboElectric 的专家,但我假设:你的问题很可能是两个框架都需要它们自己特定的@Runner 才能工作。因此:也许这个 here 有帮助;正如答案所建议的那样,一种使用 PowerMock 而不 使用 PowerMockRunner 的方法。

在 Robolectric wiki 上,您可能会找到有关如何使用 PowerMock 设置 Roboeletric 的完整说明 https://github.com/robolectric/robolectric/wiki/Using-PowerMock