11

I'm trying to use Mockito framework with android instrumentation tests but I can't initialize it correctly. I have the following test class:

class MainKontorTest extends ActivityInstrumentationTestCase2<MainActivity> {

    @Mock Dependency bar;

    @Override
    public void setUp() {
        super.setUp();
        MockitoAnnotations.initMocks(this);
    }

    public void testSomething() {
        Foo foo = new Foo(bar);
    }
}

When I try to run this test, I get the following error and stacktrace:

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.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:33) 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) at org.arkadiy.moduledelegationsample.ui.main.MainKontorTest.setUp(MainKontorTest.java:20) at junit.framework.TestCase.runBare(TestCase.java:132) at junit.framework.TestResult$1.protect(TestResult.java:115) at android.support.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:77) at junit.framework.TestResult.run(TestResult.java:118) at android.support.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:55) at junit.framework.TestCase.run(TestCase.java:124) at android.support.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:63) at junit.framework.TestSuite.runTest(TestSuite.java:243) at junit.framework.TestSuite.run(TestSuite.java:238) at android.support.test.internal.runner.junit3.DelegatingTestSuite.run(DelegatingTestSuite.java:103) at android.support.test.internal.runner.junit3.AndroidTestSuite.run(AndroidTestSuite.java:69) at android.support.test.internal.runner.junit3.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54) at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1869) 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.(Enhancer.java:70) ... 40 more Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385) at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220) ... 45 more Caused by: java.lang.UnsupportedOperationException: can't load this type of class file at java.lang.ClassLoader.defineClass(ClassLoader.java:300) ... 49 more

How can I use Mockito with Instrumentation tests? I have tried using Mockito with newer Rule api but the error was the same.

Mikhail
  • 3,666
  • 4
  • 30
  • 43
  • 1
    If you don't build your APKs using gradle, see my answer on http://stackoverflow.com/questions/29290795/attempt-to-mockito-mock-any-class-generates-exceptionininitializererror/41350001#41350001 for more information – Reuben Tanner Dec 27 '16 at 18:18

1 Answers1

15

The mocks that Mockito creates are generated class files; however, Mockito is designed for use in a JVM, so out of the box it generates .class files using cglib. Android Instrumentation test cases run on devices or emulators, so they need Dalvik .dex files.

You'll need to ensure you're including DexMaker on your classpath. The dexmaker-mockito Maven project seems to be right, though it depends on Mockito 1.10.5, which is a few versions behind at this point.

As a side note, unless you use the Android Testing Support Library, you will need to use JUnit3 semantics. You will not be able to use @Rule fields or custom test runners; you will also need to override setUp and tearDown (as opposed to @Before and @After annotations) and name your tests as testFooBar (as opposed to @Test annotations).

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Is there an example of what annotations to use, how to define the class, test methods etc? – user1743524 Sep 11 '16 at 19:12
  • If you don't build your APKs using gradle, this may not work for you. See my answer on http://stackoverflow.com/questions/29290795/attempt-to-mockito-mock-any-class-generates-exceptionininitializererror/41350001#41350001 for more information – Reuben Tanner Dec 27 '16 at 18:18
  • Why can't we use **@Rule** annotations with JUnit 4? – IgorGanapolsky Mar 09 '17 at 15:50
  • 1
    @Igor You can, but should be aware that Android instrumentation tests (which are a main reason people look to DexMaker as in this question) use JUnit 3 as their built-in library. JUnit 4 and it's `@Rule` are only available in JVM/Robolectric tests (not this question) or through the support library in my link above. – Jeff Bowman Mar 09 '17 at 15:55