Intento de mockito de simular cualquier clase genera ExceptionInInitializerError
Cuando ejecuto el código siguiente:
public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { .... public void testCanCreateMockito() { List mockedList = Mockito.mock(List.class); } }
Tengo las siguientes excepciones:
- Las pruebas de Robolectric lanzan RuntimeException: java.lang.ClassNotFoundException
- No se puede resolver la actividad para: Intención
- Cómo burlar un objeto inyectado que no se declara en el módulo?
- Prueba de unidad en la función de extensión de Kotlin en las clases de SDK de Android
- ¿Por qué realizar pruebas en un proyecto separado, en lugar de carpeta?
java.lang.ExceptionInInitializerError at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57) at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49) at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24) at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33) at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59) at org.mockito.Mockito.mock(Mockito.java:1285) at org.mockito.Mockito.mock(Mockito.java:1163) at com.acesounderglass.hungertracker.ActivityTest.testCanCreateMockito(ActivityTest.java:60) at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214) at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199) at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176) at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837) Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238) at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109) at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105) at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70) ... 23 more Caused by: java.lang.reflect.InvocationTargetException at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385) at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220) ... 28 more Caused by: java.lang.UnsupportedOperationException: can't load this type of class file at java.lang.ClassLoader.defineClass(ClassLoader.java:300) ... 32 more
Esto ocurre con cualquier clase, List era sólo un ejemplo fácil. Mis dependencias gradle son:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:21.0.0' androidTestCompile "org.mockito:mockito-core:1.+" androidTestCompile files('libs/dexmaker-mockito-1.0.jar') androidTestCompile files('libs/dexmaker-1.0.jar') }
He actualizado gradle a 1.1, intentado usar la característica experimental de la prueba de la unidad y no, nada parece hacer una diferencia. ¿Que esta pasando?
- Cómo generar informes de pruebas de Android en HTML automáticamente
- ¿Cómo burlar el método de Bundle en Android Unit-Test?
- ¿Cómo puedo rotar el emulador de Android desde el código de prueba?
- Creación de un simulador de AlarmManager para la prueba
- Cómo leer un archivo solo de prueba en la prueba de unidad de Android
- Los simulacros de Mockito ejecutan el código actual de Android en Lollipop o superior
- Prueba de la unidad MVP de Android: ¿debo burlar el bus de eventos?
- No se pueden construir pruebas con Gradle (decard-gradle)
He recibido este error cuando me faltaban las dos dependencias de dexmaker.
La adición de estas líneas al archivo app / gradle.build está funcionando para mí.
androidTestCompile 'org.mockito:mockito-core:1.10.19' androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
También estoy usando Android Studio y he encontrado que es una buena idea reiniciar AS después de alterar las dependencias.
Para mí esto funcionó:
androidTestCompile "org.mockito:mockito-core:1.10.19" androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4" androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4" androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"
Yo estaba recibiendo esto porque estaba usando proguard para mis compilaciones de depuración debido a el límite de método de 65K (Sí, necesito reducir el número de dependencias), y que estaba causando este error para mí.
He añadido esto en mi (depuración) proguard config para resolverlo:
### Keep Mockito -keep class org.mockito.** { *; } -keep interface org.mockito.** { *; } -keep class com.google.dexmaker.** { *; } -keep interface com.google.dexmaker.** { *; }
No estoy seguro Si realmente necesito las cuatro de esas líneas, pero esto hizo el truco.
Encontré el mismo error con EasyMock y eventualmente lo rastreé a una ausencia de dexmaker. Lo resolví con la siguiente dependencia:
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
Eso podría funcionar para mockito también
¡MIRE AQUÍ SI USTED NO CONSTRUYE SUS APKS USANDO GRADLE !!!!
Si no construyes tu aplicación usando gradle (lo cual, lamentablemente, mi equipo no lo hace) entonces las soluciones anteriores pueden no funcionar para ti. Permítanme explicar un poco más acerca de cómo funciona dexmaker-mockito antes de dar la solución al problema.
Motivación
Mockito es un marco burlón para Java y viene empaquetado con cglib que crea Bytecode se burla, así es como funciona Mockito / Junit fuera de Instrumentation tests. Pero si estás intentando ejecutar Mockito en las pruebas de instrumentación de Android, entonces las burlas de Bytecode no son suficientes y necesitas simulacros que Mockito puede cargar en el cargador de clase de Dex que ART / Dalvik puede entender y ahí es donde Dexmaker entra. Dexmaker tiene un plugin de Mockito "Que permite a Mockito conmutar dinámicamente a usarlo para crear mocos Dex.
¿Cómo sabe cambiar?
El tarro dexmaker-mockito tiene una carpeta de nivel superior denominada mockito-extensions/org.mockito.plugins.MockMaker
contiene un nombre completamente calificado com.google.dexmaker.mockito.DexmakerMockMaker
. Cuando esta jarra se empaqueta con un APK, esta carpeta de nivel superior se puede incluir como un "recurso de cargador de clase".
La clase que Mockito usa para abstraer la capa Mocking se llama MockUtil y, de forma estática, determina qué subclase MockMaker debería usar comprobando estos recursos en el cargador de clases que se inicia desde su PluginLoader . Si se encuentra el recurso de dexmaker-mockito, com.google.dexmaker.mockito.DexmakerMockMaker
se instancia y se utiliza como MockMaker pero, si no es así, Mockito utiliza por defecto CGLib que es incompatible en el DVM de Android.
Problema
Dependiendo de cómo construya su APK, puede quitar potencialmente ese recurso de cargador de clases y hacer que Mockito no cambie dinámicamente a usar Dexmaker.
Fijar
En primer lugar, incluya los tarros que dexmaker requiere: mockito 1.9.5+, junit, dexmaker-mockito 1.0+ y dexmaker 1.0+ y luego simplemente cambiar de forma reflexiva que MockMaker Mockito usará manualmente. Esto es seguro, dado el hecho de que si esto se está ejecutando en el DVM, el uso de CGLib MockMaker por defecto no funcionará nunca ya que produce mechas Bytecode.
static { try { ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { loader = ClassLoader.getSystemClassLoader(); } Enumeration<URL> resources = loader.getResources("mockito-extensions/org.mockito.plugins.MockMaker"); if (resources == null || !resources.hasMoreElements()) { LOGGER.info("Replacing Mockito mockMaker because the classloader resources were not present."); Field field = MockUtil.class.getDeclaredField("mockMaker"); Class<?> pluginClass = loader.loadClass("com.google.dexmaker.mockito.DexmakerMockMaker"); Object plugin = pluginClass.newInstance(); field.setAccessible(true); field.set(null, plugin); } else { LOGGER.info("Mockito class loader resources present"); } } catch (Throwable e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker", e); } else { e.printStackTrace(); throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker"); } } }
Y asegúrese de añadir esto también porque dexmaker tendrá que saber dónde dar salida a su Dex mocks.
System.setProperty("dexmaker.dexcache", "/sdcard/");
User23 respuesta está cerca de la solución que funcionó para mí.
Según la documentación oficial, debes hacer lo siguiente para activar Mockito en tu aplicación de Android:
- Descargue dexmaker-1.4.jar y dexmaker-mockito-1.4.jar y póngalos en su librería.
-
Agregue las siguientes dependencias en su build.gradle:
androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-1.4.jar'])
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-mockito-1.4.jar'])
- Botón Inicio de la barra de acciones no funcional con PreferredScreen anidado
- Petición POST de Retrofit con la autenticación HTTP básica: "No se puede reintentar el cuerpo HTTP transmitido"