运行 2 Roboelectic test-classes 与模拟相同静态 class 的 Power Mock 时出现 ClassCastException 异常
ClassCastException exception when running 2 Roboelectic test-classes with Power Mock that mocks the same static class
我有 2 个 test-classes:MyTest1 和 MyTest2。他们都有相同的 header 并测试相同的 class 但他们测试了 class 的两个截然不同的方面(你可能会因此批评我,但我们不要在这里讨论):
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = RobolectricTestData.AndroidManifestFileName)
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(MyStrangeClassWithStaticMethods.class)
@ParametersAreNonnullByDefault
public class MyTest1 extends MyBaseTest {
// This is to dinamically load PowerMock. We can't use PowerMockRunner because we already use
// RobolectricTestRunner and PowerMockRunner doesn't do robolectric's stuff.
@Rule
public final PowerMockRule rule = new PowerMockRule();
/**
* Tests set up.
*/
@Before
public final void setUp() throws Exception {
super.setUp();
}
public void testSomething() {
PowerMockito.mockStatic(MyStrangeClassWithStaticMethods.class);
// do some stuff
}
}
问题是我可以 运行 单独的 MyTest1 并且所有测试都正常。我可以单独 运行 MyTest2 并且所有测试都正常。但是当我 运行 MyTest1 和 MyTest2 的所有测试(它们被编译到一个 jar 中)时 - 当我这样做时,只有第一个 运行 class (MyTest1) 正常,第二个 class 失败。
所有测试均因此异常而崩溃:
org.mockito.exceptions.base.MockitoException:
ClassCastException occurred while creating the mockito proxy :
class to imposterize : 'com.my.project.MyStrangeClassWithStaticMethods', loaded by classloader : 'org.powermock.core.classloader.MockClassLoader@2617b42c'
imposterizing class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader@230eec25'
proxy instance class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader@23a0547b'
You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:109)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:57)
at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
at com.my.project.MyTest2.testSomething(MyTest2.java:66666<no matter what line number>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.powermock.modules.junit4.rule.PowerMockStatement.run(PowerMockRule.java:52)
at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:638)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)
at org.robolectric.RobolectricTestRunner.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.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:50)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.chromium.testing.local.GtestComputer$GtestSuiteRunner.run(GtestComputer.java:46)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:50)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.chromium.testing.local.JunitTestMain.main(JunitTestMain.java:105)
Caused by: java.lang.ClassCastException: Cannot cast com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512 to com.my.project.MyStrangeClassWithStaticMethods
at java.lang.Class.cast(Class.java:3176)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
... 47 more
这次崩溃迫使我将我的 2 classes 合并到 1 个测试 class 中。这可能会阻止我在另一个测试 class 中模拟 MyStrangeClassWithStaticMethods.class 的可能性。我只能嘲笑一次:(
问题看起来像 ClassCastException exception when running Robolectric test with Power Mock on multiple files,但有点不同,需要其他解决方案。
Powermock 1.6.0
Mockito 1.10.5
Robolectric 3.0
我找到了解决办法。堆栈跟踪显示:
disabling the Objenesis cache might help (see MockitoConfiguration)
我做到了并且成功了。只需将此 class 添加到您的测试源位置:
package org.mockito.configuration;
public class MockitoConfiguration extends DefaultMockitoConfiguration {
@Override
public boolean enableClassCache() {
return false;
}
}
我有 2 个 test-classes:MyTest1 和 MyTest2。他们都有相同的 header 并测试相同的 class 但他们测试了 class 的两个截然不同的方面(你可能会因此批评我,但我们不要在这里讨论):
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = RobolectricTestData.AndroidManifestFileName)
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest(MyStrangeClassWithStaticMethods.class)
@ParametersAreNonnullByDefault
public class MyTest1 extends MyBaseTest {
// This is to dinamically load PowerMock. We can't use PowerMockRunner because we already use
// RobolectricTestRunner and PowerMockRunner doesn't do robolectric's stuff.
@Rule
public final PowerMockRule rule = new PowerMockRule();
/**
* Tests set up.
*/
@Before
public final void setUp() throws Exception {
super.setUp();
}
public void testSomething() {
PowerMockito.mockStatic(MyStrangeClassWithStaticMethods.class);
// do some stuff
}
}
问题是我可以 运行 单独的 MyTest1 并且所有测试都正常。我可以单独 运行 MyTest2 并且所有测试都正常。但是当我 运行 MyTest1 和 MyTest2 的所有测试(它们被编译到一个 jar 中)时 - 当我这样做时,只有第一个 运行 class (MyTest1) 正常,第二个 class 失败。 所有测试均因此异常而崩溃:
org.mockito.exceptions.base.MockitoException:
ClassCastException occurred while creating the mockito proxy :
class to imposterize : 'com.my.project.MyStrangeClassWithStaticMethods', loaded by classloader : 'org.powermock.core.classloader.MockClassLoader@2617b42c'
imposterizing class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader@230eec25'
proxy instance class : 'com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512', loaded by classloader : 'org.mockito.internal.creation.jmock.SearchingClassLoader@23a0547b'
You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:109)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:57)
at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
at com.my.project.MyTest2.testSomething(MyTest2.java:66666<no matter what line number>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.powermock.modules.junit4.rule.PowerMockStatement.run(PowerMockRule.java:52)
at sun.reflect.GeneratedMethodAccessor26.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1873)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:773)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:638)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98)
at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49)
at org.robolectric.RobolectricTestRunner.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.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:50)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.chromium.testing.local.GtestComputer$GtestSuiteRunner.run(GtestComputer.java:46)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:50)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.chromium.testing.local.JunitTestMain.main(JunitTestMain.java:105)
Caused by: java.lang.ClassCastException: Cannot cast com.my.project.MyStrangeClassWithStaticMethods$$EnhancerByMockitoWithCGLIB$f09512 to com.my.project.MyStrangeClassWithStaticMethods
at java.lang.Class.cast(Class.java:3176)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:62)
... 47 more
这次崩溃迫使我将我的 2 classes 合并到 1 个测试 class 中。这可能会阻止我在另一个测试 class 中模拟 MyStrangeClassWithStaticMethods.class 的可能性。我只能嘲笑一次:(
问题看起来像 ClassCastException exception when running Robolectric test with Power Mock on multiple files,但有点不同,需要其他解决方案。
Powermock 1.6.0
Mockito 1.10.5
Robolectric 3.0
我找到了解决办法。堆栈跟踪显示:
disabling the Objenesis cache might help (see MockitoConfiguration)
我做到了并且成功了。只需将此 class 添加到您的测试源位置:
package org.mockito.configuration;
public class MockitoConfiguration extends DefaultMockitoConfiguration {
@Override
public boolean enableClassCache() {
return false;
}
}