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:

 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?

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/"); 

Mockito-extensions / org.mockito.plugins.MockMaker

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:

  1. Descargue dexmaker-1.4.jar y dexmaker-mockito-1.4.jar y póngalos en su librería.
  2. 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'])

  • Android: cómo obtener el contexto cuando se prueba con ActivityInstrumentationTestCase2?
  • Android @NonNull utilidad
  • Googletest para Android NDK
  • Unidad Método de prueba que no contiene lambda expresión Android Studio
  • Schedulers.immediate () no funciona con las pruebas de gradle de la línea de comandos
  • Robolectric: NotFoundException: recurso desconocido 0 en org.robolectric.shadows.ShadowAssetManager.getAndResolve (ShadowAssetManager.java:258)
  • Utilice @Ignore en AndroidTestCase
  • Robolectric Unit Test falla con las actualizaciones de Android Studio 2.3
  • Cómo llamar a Button.performClick en Android JUnit test case?
  • Prueba de la unidad Android: Bundle / Parcelable
  • ¿Ejecutar pruebas de unidad android desde la línea de comandos?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.