在编写单元测试用例的时候,如果被测试类是与AIDL相关的类,不管是直接调用,还是被测试类继承了AIDL生成的类,由于AIDL类是在编译期间动态生成的,并且每次构建都会重新生成一次(类名相同,但是Hash可能会变,文件修改日期必然变更)。
然而,由于PowerMock调用Objenesis库为了加快编译速度,会缓存同名的类,这样导致在运行时进行类型转换的时候无法通过校验,报告如下错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
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 |
解决方法就是阻止Objenesis的缓存功能。在测试用例的根目录下新建文件,如下:
1 2 3 4 5 6 7 8 9 |
package org.mockito.configuration; public class MockitoConfiguration extends DefaultMockitoConfiguration { @Override public boolean enableClassCache() { return false; } } |
参考链接
- How can I test class extends auto-generated Stub class from AIDL file
- How to test remote android aidl service
- Mockito ClassCastException after using PowerMock
- ClassCastException exception when running Robolectric test with Power Mock on multiple files
- Mockito ClassCastException after using PowerMock