尝试mockito模拟任何类生成ExceptionInInitializerError

当我运行下面的代码:

public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { .... public void testCanCreateMockito() { List mockedList = Mockito.mock(List.class); } } 

我得到以下例外:

 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 

这发生在任何类,列表只是一个简单的例子。 我的gradle依赖是:

 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') } 

我已经将gradle升级到1.1,试过使用实验unit testingfunction,而没有任何东西似乎有所作为。 这是怎么回事?

Solutions Collecting From Web of "尝试mockito模拟任何类生成ExceptionInInitializerError"

我错过了两个dexmaker依赖关系时收到这个错误。

将这些行添加到app / gradle.build文件正在为我工​​作。

 androidTestCompile 'org.mockito:mockito-core:1.10.19' androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' 

我也在使用Android Studio,并发现改变依赖关系后重新启动AS是一个好主意。

对我来说,这最终奏效了:

 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" 

我得到这个,因为我正在使用proguard我的debugging版本,因为65K方法的限制(是的,我需要减less依赖的数量),这是造成这个错误。

我在我的(debugging)proguardconfiguration中添加这个来解决它:

 ### Keep Mockito -keep class org.mockito.** { *; } -keep interface org.mockito.** { *; } -keep class com.google.dexmaker.** { *; } -keep interface com.google.dexmaker.** { *; } 

不知道如果我真的需要所有这四行,但这个伎俩。

我遇到了与EasyMock相同的错误,并最终将其追溯到dexmaker的缺席。 我解决了它与以下依赖项:

 androidTestCompile "com.google.dexmaker:dexmaker:1.2" 

这可能也适用于mockito

看这里,如果你不build立你的APK使用等级!

如果您不使用gradle构build您的应用程序(不幸的是,我的团队不这样做),那么上述解决scheme可能无法为您工作。 让我更详细地解释dexmaker-mockito在解决问题之前是如何工作的。

动机

Mockito是Java的一个模拟框架,并附带了创buildBytecode mock的cglib,这是Instrumentationtesting之外的Mockito / Junit的工作原理。 但是,如果你想在Android仪器testing中运行Mockito,那么Bytecode mock是不够的,你需要Mockito可以加载到ART / Dalvik可以理解的Dex类加载器中,这就是Dexmaker进来的地方。Dexmaker有一个Mockito“插件“这允许Mockitodynamic地切换到使用它来创buildDex嘲笑。

它如何知道切换?

dexmaker-mockito jar包含一个名为mockito-extensions/org.mockito.plugins.MockMaker的顶级文件夹,其中包含一个完全限定的名称com.google.dexmaker.mockito.DexmakerMockMaker 。 当这个jar与APK打包时,这个顶层文件夹可以作为“类加载器资源”被包含。

Mockito用来抽象Mocking层的类被称为MockUtil ,静态地,它通过检查类加载器中通过PluginLoader启动的这些资源来确定应该使用哪个MockMaker子类。 如果可以find来自dexmaker-mockito的资源,那么com.google.dexmaker.mockito.DexmakerMockMaker被实例化并用作MockMaker,但如果不是,Mockito默认使用在Android的DVM中不兼容的CGLib。

问题

根据你如何构build你的APK,你可能会剥夺这个类加载器资源,并导致Mockito不能dynamic切换到使用Dexmaker。

固定

首先,包括dexmaker需要的jar子:mockito 1.9.5+,junit,dexmaker-mockito 1.0+和dexmaker 1.0+,然后简单地reflection切换MockMaker Mockito将手动使用的jar子。 这是安全的,因为如果这是在DVM中运行,使用默认的CGLib MockMaker将无法工作,因为它会产生字节码模拟。

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

并且一定要添加这个,因为dexmaker需要知道在哪里输出它的Dex嘲笑。

 System.setProperty("dexmaker.dexcache", "/sdcard/"); 

的Mockito的扩展/ org.mockito.plugins.MockMaker

User23的答案接近为我工作的解决scheme。

根据官方文档,你必须做以下的事情来激活你的Android应用程序Mockito:

  1. 下载dexmaker-1.4.jar和dexmaker-mockito-1.4.jar并将它们放到libs文件夹中。
  2. 将以下依赖项添加到您的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'])