unit-testing - 在多个文件上使用 Power Mock 运行 Robolectric 测试时出现 ClassCastException 异常

标签 unit-testing robolectric powermock android-testing powermockito

所以我根据引用指南 here 设置了 power mock .使用单个测试类,这一切似乎都运行得很好。但是在执行多个 JUnit 测试时,我在第二个测试类上收到以下错误。

正如您从下面的堆栈跟踪中看到的那样,我正在尝试模拟 otto Bus 实例。它似乎在第一个测试类中正确模拟,但在第二个类中,我收到了此类转换异常。

在堆栈跟踪中,我收到了禁用 Objenisis 缓存的建议,但我不确定如何实现这一点,如果这实际上是我使用 classloading-xstream:1.6.2 的根本原因,根据上面附加的 Robolectric Wiki 链接。

问题是,如果我运行单个 JUnit 测试类,我的设置运行良好,但是一旦我尝试在一个包中运行所有测试,只有第一个测试将起作用,后续测试将获得类转换异常。

org.mockito.exceptions.base.MockitoException: 
    ClassCastException occurred while creating the mockito proxy :
      class to mock : 'com.squareup.otto.Bus', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@1593948d'
      created class : 'com.squareup.otto.Bus$$EnhancerByMockitoWithCGLIB$$82a3b196', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@1593948d'
      proxy instance class : 'com.squareup.otto.Bus$$EnhancerByMockitoWithCGLIB$$82a3b196', loaded by classloader : 'org.mockito.internal.creation.util.SearchingClassLoader@618ff5c2'
      instance creation by : ObjenesisInstantiator

    You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:61)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
        at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
        at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:45)
        at com.acme.android.myapp.services.gcm.handlers.RequestLogoutHandlerTest.setup(RequestLogoutHandlerTest.java:39)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
        at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
        at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
        at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
        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.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        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 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
    Caused by: java.lang.ClassCastException: Cannot cast com.squareup.otto.Bus$$EnhancerByMockitoWithCGLIB$$82a3b196 to com.squareup.otto.Bus
        at java.lang.Class.cast(Class.java:3369)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:59)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
        at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
        at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:45)
        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)
        ... 36 more


    org.mockito.exceptions.base.MockitoException: 
    ClassCastException occurred while creating the mockito proxy :
      class to mock : 'com.squareup.otto.Bus', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@1593948d'
      created class : 'com.squareup.otto.Bus$$EnhancerByMockitoWithCGLIB$$82a3b196', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@1593948d'
      proxy instance class : 'com.squareup.otto.Bus$$EnhancerByMockitoWithCGLIB$$82a3b196', loaded by classloader : 'org.mockito.internal.creation.util.SearchingClassLoader@618ff5c2'
      instance creation by : ObjenesisInstantiator

    You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:61)
        at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:49)
        at org.powermock.api.mockito.repackaged.CglibMockMaker.createMock(CglibMockMaker.java:24)
        at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.createMock(PowerMockMaker.java:45)
        at com.acme.android.myapp.services.gcm.handlers.RequestLogoutHandlerTest.setup(RequestLogoutHandlerTest.java:39)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
        at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
        at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
        at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
        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.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        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 com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:6

最佳答案

我建议按照异常消息中的建议禁用 Mockito 的 ClassCache
.
这是我通过在 Android Studio 中添加 MockitoConfiguration 类来禁用 Mockito ClassCache 的方法。

  • 在您的单元测试目录 src/test/java 下,创建一个与 Mockito 配置包完全相同的包目录 org/mockito/configuration。
  • 所以在完整的测试目录 src/test/java/org/mockito/configuration 下,添加一个名为 MockitoConfiguration 的新类。
  • 如下覆盖 enableClassCache() 方法。
    package org.mockito.configuration;
    
        public class MockitoConfiguration extends DefaultMockitoConfiguration {
    
        @Override
        public boolean enableClassCache() {
            return false;
        }
    }
    
  • 当你在 src/java/test 下运行你的单元测试时,你的 MockitoConfiguration 应该被加载并且 Mockito 类缓存应该被禁用。

  • 希望能帮助到你。

    关于unit-testing - 在多个文件上使用 Power Mock 运行 Robolectric 测试时出现 ClassCastException 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33008255/

    相关文章:

    android - 使用 Robolectric 测试 okHttp 请求 - 回调

    swing - 调用 super() JDialog 时的 Powermock,Mockito nullpointerexception

    c# - AutoMapper 空源值和自定义类型转换器,映射失败?

    unit-testing - 找不到 dotnet 测试 id : error in Resharper 2016. 3 的元素

    java - 在 Robolectric 测试中使用 Android KeyStore

    android - 在我的测试中我需要 Robolectric 和 Mockito,每个人都提出自己的 TestRunner

    unit-testing - 单元测试中的单位是什么?它应该是什么?

    unit-testing - 对 Azure Functions 和 .csx 文件进行单元测试

    java - 如何使用 REFLECTION 或任何其他 API 初始化最终类中的私有(private)变量?

    powermock - 使用 powermock 模拟 super 实现