Mockito with Robolectric: "ClassCastException occurred while creating proxy"

I started to hit the weird ClassCastException in Mockito when using it with Robolectric. When I run the same tests without using the Robolectric runner, everything goes well, no exception is thrown.

Here is the stack trace:

org.mockito.exceptions.base.MockitoException: ClassCastException occurred when creating the proxy. You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration) at com.compassrosetech.ccs.android.test.ObservableCacheDispatcherTest.setUp(ObservableCacheDispatcherTest.java:63) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.junit.runner.JUnitCore.run(JUnitCore.java:160) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) Caused by: java.lang.ClassCastException: kotlin.Function0$$EnhancerByMockitoWithCGLIB$$c0163e7f cannot be cast to org.mockito.cglib.proxy.Factory at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128) at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63) at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56) at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51) at org.mockito.Mockito.mock(Mockito.java:1243) at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:30) at org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:16) at org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(DefaultAnnotationEngine.java:43) at org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnotationEngine.java:66) at org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:71) at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:55) at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108) ... 29 more 

The code I use is as follows:

 @RunWith(ApplicationTestRunner.class) public class ObservableCacheDispatcherTest { @Mock private IDataMapper mockDataMapper; @Mock private ICache mockCache; @Mock private Function0<Object> mockLoader; private ObservableCacheDispatcher cacheDispatcher; @Before public void setUp() { MockitoAnnotations.initMocks(this); // <-- exception happens when executing this statement cacheDispatcher = new ObservableCacheDispatcher(mockCache, mockDataMapper); } ... } 

Here's what a Robolectric runner looks like:

 public class ApplicationTestRunner extends RobolectricTestRunner { //Maximun SDK Robolectric will compile (issues with SDK > 18) private static final int MAX_SDK_SUPPORTED_BY_ROBOLECTRIC = 18; private static final String ANDROID_MANIFEST_PATH = "../app/src/main/AndroidManifest.xml"; private static final String ANDROID_MANIFEST_RES_PATH = "../app/src/main/res"; /** * Call this constructor to specify the location of resources and AndroidManifest.xml. * * @throws org.junit.runners.model.InitializationError */ public ApplicationTestRunner(Class<?> testClass) throws InitializationError { super(testClass); } @Override protected AndroidManifest getAppManifest(Config config) { return new AndroidManifest(Fs.fileFromPath(ANDROID_MANIFEST_PATH), Fs.fileFromPath(ANDROID_MANIFEST_RES_PATH)) { @Override public int getTargetSdkVersion() { return MAX_SDK_SUPPORTED_BY_ROBOLECTRIC; } }; } } 

What should I fix to get rid of this exception?

+6
source share
5 answers

As suggested

'disabling Objenesis cache may help'

You can create an override of MockitoConfiguration.
For this

  • Create a package called org.mockito.configuration under your src / test / java
  • Enter the MockitoConfiguration class

Class file

 package org.mockito.configuration; public class MockitoConfiguration extends DefaultMockitoConfiguration { @Override public boolean enableClassCache() { return false; } } 

Try creating the code again.

+7
source

In fact, this is not Kotlin’s problem, but Robolectric / Mockito. I believe this is due to class loaders. If you replace the Kotlin class with some other library interface (neither the JDK, nor your project class), you will see the same exception. Unfortunately, I do not see a solution, because I do not understand the insides of Robolectric. You better ask Robolectric or Mockito about this.

+1
source

I had a similar problem. Basically, you have some classes that you want the Mockito layout and other classes that you want PowerMock to make fun of. I solved this by adding the @PowerMockIngore annotation to my test class and specifying the classes that I wanted to make fun of using the regular "ol mockito". So in your case, I think adding annotation:

 @PowerMockIgnore({"com.package.IDataMapper", "com.package.ICache" ..etc}) 

will work.

+1
source

Caution!

Please use at your own risk.

You must first redefine the kotlin functional interfaces:

 interface TestFunction0<R> : Function0<R> interface TestFunction1<T1, R> : Function1<T1, R> 

And make fun of it:

 val onUpdate: TestFunction0<Unit> = mock() 
+1
source

I know the question is a bit outdated, but it can help someone find the answer.

Adding

 @PowerMockIgnore({ "org.mockito.*"}) 

After

 @RunWith(ApplicationTestRunner.class) 

Should solve the problem.

0
source

Source: https://habr.com/ru/post/983848/


All Articles