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:
- Obtenga día, mes y año por separado usando SimpleDateFormat
- ¿Por qué Android dibuja Vista dentro de otra (con anchura y altura definidas en píxeles) de manera incorrecta?
- ¿Puedo borrar la parte o el contenido de una imagen que se carga desde la tarjeta SD al lienzo o DrawView
- Uso de un servicio de Android para manejar una conexión de red
- Adjuntar fuentes de SDK de Android en Eclipse
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?
- Cómo guardar la lista <Object> a SharedPreferences?
- Establecer notificación en un momento específico android
- ¿Cuál usar? JSONObject de org.json VS JsonObject de javax.json
- StateListDrawable para cambiar filtros de color
- Ocultar la interfaz de usuario del sistema en Lollipop
- Conexión XMPP con Smack 4.1 en Android Studio
- Necesito una explicación para el código de "inicio de juegos android"
- Convertir valor segundos a horas minutos segundos?
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.
- Reproducir sonido en las notificaciones de Android, aunque el modo de silencio del teléfono se establece
- Android FragmentActivity devuelve null en getActionBar ()