Robolectric + PowerMock + Mockito not working

2.6k Views Asked by At

I'm struggling to get this rare combination works, but I haven't got luck. My project uses JUnit + Mockito + Robolectric for testing and Roboguice for injection, when I added PowerMock to the equation weird things happened, this are some of the things I've tried:

1.- Out of the box PowerMock + Mockito + Robolectic integration. As suggested on PowerMockIngration, I added a @PowerMockRunnerDelegate to include my custom runner which extends from RobolectricGradleTestRunner:

Build.gradle

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

Test

@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);
    ....
  }

Result:

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)...

So is like @PrepareForTest is nor working, then I tried when a rule a class loader, as suggested in the same guide:

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"

Test Class

@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);
   ...
  }

At this point the test passes and I was able to mock RoboGuice as expected, BUT when I ran all my test cases together I start getting the following exception when creating a simple mock like 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)

So I tried a lots of variants: Remove the xtream class loader:

  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)

User 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

So I running out of ideas, anyone??

1

There are 1 best solutions below

0
Mateusz Dziekan On

I had the same problem.

My solution was to:

  • remove testCompile "org.powermock:powermock-module-junit4-rule-agent:x.x.x" from gradle

  • change import static *.Mockito.mock and *.Mockito.when to org.powermock.api.mockito.PowerMockito.mock and org.powermock.api.mockito.PowerMockito.when.