Java 如何结合PowerMock和Robolectric

Java 如何结合PowerMock和Robolectric,java,unit-testing,powermock,robolectric,powermockito,Java,Unit Testing,Powermock,Robolectric,Powermockito,我有一个静态方法,使用上下文检查internet状态。所以要模拟它,我需要使用PowerMock。我正在使用robolectric来加速我的测试,因为我唯一需要模拟的东西就是模拟的。但我似乎无法配置PowerMock(1.6.6)和Robolectric(3.2.2)一起工作。以下是我如何注释我的类: @RunWith(RobolectricTestRunner.class) @org.robolectric.annotation.Config(constants = BuildConfig.c

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

@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$1.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$2.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$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:199)
My 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"

有时候,答案是简单地退一步,看看您使用PowerMock的“需要”

那么,您有一个静态方法需要PowerMock才能测试

然后,简单地避免使代码成为静态的。然后,您对使用PowerMock的需求就消失了

简单地将其替换为接口、impl类(如果您需要“恰好”它的一个实现,还可能是枚举单例)的组合

我向您保证:不需要PowerMock是更好的选择;相比之下,花很多时间让它与另一个字节码操作框架一起工作

或者换句话说:学习如何编写可测试的代码,并做到这一点;与其创建难以测试的代码,还需要强大的PowerMock锤子来实现可测试性。观看这些,了解如何做到这一点


我不是RoboeElectric的专家,但我认为:问题很可能是这两个框架都需要自己特定的@Runner才能工作。因此:也许这有帮助;正如答案所示,使用PowerMock而不使用PowerMockRunner的方法

在Robolectric wiki上,您可以找到如何使用PowerMock设置Roboeletric的完整说明

是的,你是对的。但如果我知道如何让robolectric和PowerMock一起工作,那也很好;我会把它写下来。。。但是,我有了一个想法并更新了我的答案。也许这会有帮助。