Robolectric + PowerMock + Mockito无法正常工作

Jav*_*209 10 junit android roboguice robolectric powermockito

我很难得到这种罕见的组合作品,但我没有运气.我的项目使用JUnit + Mockito + Robolectric进行测试和Roboguice进行注射,当我将PowerMock添加到方程式时发生了奇怪的事情,这是我尝试过的一些事情:

1.-开箱即用的PowerMock + Mockito + Robolectic集成.正如在PowerMockIngration上所建议的那样,我添加了一个@PowerMockRunnerDelegate包括我的自定义运行器,它包括RobolectricGradleTestRunner:

的build.gradle

  testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'
Run Code Online (Sandbox Code Playgroud)

测试

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MyCustomRunner.class)
@Config(constants = BuildConfig.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest(RoboGuice.class)
public class Test {

  @Before
  public void setUp() throws Exception {
    PowerMockito.mockStatic(RoboGuice.class);
    ....
  }
Run Code Online (Sandbox Code Playgroud)

结果:

java.lang.IllegalArgumentException: Cannot subclass final class class roboguice.RoboGuice at org.mockito.cglib.proxy.Enhancer.generateClass(Enhancer.java:447) 
 at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.createProxyClass(ClassImposterizer.java:123)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:57)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:111)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:59)
    at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
    at com.humana.vitalityapp.activity.BaseVitalityActivityTest.setUp(BaseVitalityActivityTest.java:79)
    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:497)
    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.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    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:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:146)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:130)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)...
Run Code Online (Sandbox Code Playgroud)

所以就像@PrepareForTest是工作,然后我尝试了一个规则类加载器,如同在同一指南中所建议:

的build.gradle

  testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile "org.powermock:powermock-module-junit4-rule:1.6.4"
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'
  testCompile "org.powermock:powermock-classloading-xstream:1.6.4"
Run Code Online (Sandbox Code Playgroud)

测试类

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MyCustomRunner.class)
@Config(constants = BuildConfig.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest(RoboGuice.class)
public class Test { 
  @Rule public PowerMockRule rule = new PowerMockRule();

@Before
  public void setUp() throws Exception {
    PowerMockito.mockStatic(RoboGuice.class);
   ...
  }
Run Code Online (Sandbox Code Playgroud)

此时测试通过,我能够按预期模拟RoboGuice,但是当我将所有测试用例一起运行时,我在创建一个简单的模拟时开始得到以下异常mock(OtherClass.class):

org.mockito.exceptions.base.MockitoException: 
ClassCastException occurred while creating the mockito proxy :
  class to mock : 'com.humana.vitalityapp.analytics.Analytics', loaded by classloader : 'org.powermock.core.classloader.MockClassLoader@168fa63d'
  created class : 'com.humana.vitalityapp.analytics.Analytics$$EnhancerByMockitoWithCGLIB$$67cb81b1', loaded by classloader : 'org.mockito.internal.creation.util.SearchingClassLoader@20f5a6b6'
  proxy instance class : 'com.humana.vitalityapp.analytics.Analytics$$EnhancerByMockitoWithCGLIB$$67cb81b1', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@6fdbe764'
  instance creation by : ObjenesisInstantiator

You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)

    at com.humana.vitalityapp.activity.BaseVitalityActivityTest.setUp(BaseVitalityActivityTest.java:77)
    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:497)
    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.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:65)
    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:497)
Run Code Online (Sandbox Code Playgroud)

所以我尝试了很多变种:删除xtream类加载器:

  java.lang.RuntimeException: java.lang.ClassNotFoundException: org.powermock.classloading.DeepCloner

    at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:68)
    at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:34)
Run Code Online (Sandbox Code Playgroud)

用户JunitAgent:

 testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile "org.powermock:powermock-module-junit4-rule-agent:1.6.4"
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'

Caused by: java.lang.IllegalStateException: PowerMockRule can only be used with the system classloader but was loaded by org.robolectric.internal.bytecode.InstrumentingClassLoader@2a7f1f10
Run Code Online (Sandbox Code Playgroud)

所以我用完了想法,任何人?

小智 0

我有同样的问题。

我的解决方案是:

  • testCompile "org.powermock:powermock-module-junit4-rule-agent:x.x.x"从 gradle 中删除

  • 将 import static *.Mockito.mock 和 *.Mockito.when 更改为org.powermock.api.mockito.PowerMockito.mockorg.powermock.api.mockito.PowerMockito.when