使用Mockito进行Android仪器测试

11

我正在尝试在Android的Instrumentation测试中使用Mockito框架,但无法正确初始化。我有以下测试类:

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

当我尝试运行此测试时,我会收到以下错误和堆栈跟踪:
java.lang.ExceptionInInitializerError 在 org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95) 中创建代理类 在 org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57) 中模仿 在 org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49) 中模仿 在 org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24) 中创建模拟对象 在 org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33) 中创建模拟对象 在 org.mockito.internal.MockitoCore.mock(MockitoCore.java:59) 中创建模拟对象 在 org.mockito.Mockito.mock(Mockito.java:1285) 中创建模拟对象 在 org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:33) 中处理注释 在 org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotationProcessor.java:16) 中处理注释 在 org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(DefaultAnnotationEngine.java:43) 中为默认注释引擎创建模拟对象 在 org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnotationEngine.java:66) 中处理注释 在 org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentAnnotations(InjectingAnnotationEngine.java:71) 中处理独立注释 在 org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:55) 中处理注释 在 org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108) 中初始化模拟对象 在 org.arkadiy.moduledelegationsample.ui.main.MainKontorTest.setUp(MainKontorTest.java:20) 中设置 在 junit.framework.TestCase.runBare(TestCase.java:132) 中运行单元测试 在 junit.framework.TestResult$1.protect(TestResult.java:115) 中保护 在 android.support.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:77) 中保护 在 junit.framework.TestResult.run(TestResult.java:118) 中运行单元测试 在 android.support.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:55) 中运行单元测试 在 junit.framework.TestCase.run(TestCase.java:124) 中运行单元测试 在 android.support.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:63) 中运行单元测试 在 junit.framework.TestSuite.runTest(TestSuite.java:243) 中运行测试套件 在 junit.framework.TestSuite.run(TestSuite.java:238) 中运行测试套件 在 android.support.test.internal.runner.junit3.DelegatingTestSuite.run(DelegatingTestSuite.java:103) 中委托运行测试套件 在 android.support.test.internal.runner.junit3.AndroidTestSuite.run(AndroidTestSuite.java:69) 中运行 Android 测试套件 在 android.support.test.internal.runner.junit3.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90) 中运行 JUnit38 类运行器 在 org.junit.runners.Suite.runChild(Suite.java:128) 中运行子套件 在 org.junit.runners.Suite.runChild(Suite.java:27) 中运行子套件 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 中运行 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 中调度 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 中运行子运行器 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 中访问 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 中评估 在 org.junit.runners.ParentRunner.run(ParentRunner.java:363) 中运行 在 org.junit.runner.JUnitCore.run(JUnitCore.java:137) 中运行 JUnitCore 在 org.junit.runner.JUnitCore.run(JUnitCore.java:115) 中运行 JUnitCore 在 android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:54) 中执行测试 在 android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:240) 中开始运行 AndroidJUnitRunner 在 android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1869) 中运
我该如何在仪器化测试中使用Mockito?我尝试过使用较新的Rule api,但错误仍然存在。

1
如果您不是使用gradle构建APK,请查看我的答案,了解更多信息:https://dev59.com/MV4b5IYBdhLWcg3wVwJi#41350001 - Reuben Tanner
1个回答

15

Mockito创建的模拟对象是生成的类文件; 但是,Mockito是为在JVM中使用而设计的,因此它默认使用cglib生成.class文件。Android Instrumentation测试用例在设备或模拟器上运行,因此它们需要Dalvik.dex文件。

您需要确保在类路径中包含DexMakerdexmaker-mockito Maven项目似乎是正确的选择,但它依赖于Mockito 1.10.5,这个版本已经有些过时了。

作为一个旁注,除非您使用 Android测试支持库,否则您将需要使用JUnit3语义。您将无法使用@Rule字段或自定义测试运行器;您还需要覆盖setUptearDown(而不是@Before@After注释),并将您的测试命名为testFooBar(而不是@Test注释)。

有没有关于使用哪些注解、如何定义类、测试方法等的示例? - user1743524
如果您不使用gradle构建您的APK,则此方法可能无法正常工作。请参阅我的答案https://dev59.com/MV4b5IYBdhLWcg3wVwJi#41350001以获取更多信息。 - Reuben Tanner
为什么我们不能在JUnit 4中使用**@Rule**注释? - IgorGanapolsky
1
@Igor,你可以这样做,但应该知道,Android测试框架(这也是人们在这个问题中寻找DexMaker的主要原因之一)使用JUnit 3作为其内置库。而JUnit 4及其@Rule只能在JVM / Robolectric测试中使用(与此问题无关),或通过我上面提供的支持库使用。 - Jeff Bowman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接