Mockito con Robolectric: "ClassCastException se produjo al crear el proxy"

He empezado a golpear una extraña ClassCastException en Mockito cuando la uso con Robolectric. Cuando ejecuto las mismas pruebas no usando corredor Robolectric, todo va bien, no se lanza ninguna excepción.

Aquí está el rastreo de la pila:

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 

El código que estoy usando es el siguiente:

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

Así es como se ve el corredor de Robolectric:

 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; } }; } } 

¿Qué debo arreglar para deshacerme de esta excepción?

Como se sugirió

'Deshabilitar la caché Objenesis podría ayudar'

Puede crear la modificación MockitoConfiguration.
Para ello

  • Cree un paquete denominado org.mockito.configuration bajo su src / test / java
  • Escribe la clase MockitoConfiguration

Archivo de clase

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

Intente crear su código de nuevo.

Esto no es realmente cuestión de Kotlin pero Robolectric / Mockito. Creo que está relacionado con los cargadores de clase. Si reemplaza la clase Kotlin con cualquier otra interfaz de biblioteca (ni JDK ni la clase de su proyecto) verá la misma excepción. Lamentablemente no veo ninguna solución ya que no entiendo Robolectric internos. Es mejor preguntar a los equipos de Robolectric o Mockito sobre esto.

He tenido un problema similar. Básicamente, tienes algunas clases que quieres que Mockito mock y otras clases que quieras que PowerMock se burlen. Lo solucioné agregando la anotación @PowerMockIngore a mi clase de prueba y especificando las clases que quería simular usando regular 'ol mockito. Así que en su caso, creo que añadir la anotación:

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

trabajaría.

¡Advertencia sobre la solución!

Por favor, use bajo su propio riesgo.

Primero tienes que redefinir las interfaces de la función kotlin:

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

Y burlarse de ella:

 val onUpdate: TestFunction0<Unit> = mock() 

Sé que la pregunta es un poco vieja, pero puede ayudar a alguien que busca la respuesta.

Añadiendo

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

Después

 @RunWith(ApplicationTestRunner.class) 

Debe resolver el problema.

  • ¿Cómo escuchar los eventos completos de carga de Picasso (Android)?
  • ¿Qué hace la palabra clave esta referencia en este ejemplo de código?
  • Cómo Caché los datos de Json para estar disponibles sin conexión?
  • Problemas incluyendo Apache HttpComponents en el proyecto de Android Gradle
  • Error de registro de vídeo de Android
  • ¿Cuál es el propósito de las anotaciones de @SmallTest, @MediumTest y @LargeTest en Android?
  • Cómo obtener el valor de atributo personalizado de un mensaje XMPP XML?
  • Obtener el valor lux del sensor de luz sin evento onSensorChanged ()?
  • Rellene los datos del sitio web y haga clic en el botón y analizar la respuesta.
  • ¿Qué significa "servicio semipúblico" en Android?
  • JSONObject devuelve un valor no nulo de "null" después de instanciar con cadena
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.