使用PowerMock和Robolectric – IncompatibleClassChangeError

我正在尝试使用PowerMockito来模拟Android Robolectrictesting中的一些静态方法。 我正在使用JUnit 4.8.2,Robolectric 2.2,Mockito 1.9.5和PowerMock 1.9.5。 由于我必须使用RoboElectricTestRunner ,所以我试图使用PowerMockRule来引导PowerMock。 不过,当运行PowerMock的testing时,我得到了一个不幸的java.lang.IncompatibleClassChangeError

java.lang.reflect.InvocationTargetException
在sun.reflect.NativeMethodAccessorImpl.invoke0(本地方法)
在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)
在sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323)at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:348)

引起:java.lang.IncompatibleClassChangeError:在java.lang.ClassLoader.defineClass1上实现类(Native Method)
java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)at java.lang.ClassLoader.defineClass(ClassLoader.java:621)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)

如果我把org.ow2.asm库之后的org.powermock得到:

java.lang.IncompatibleClassChangeError:org.objectweb.asm.tree.ClassNode org.objectweb.asm.ClassNode org.objectweb.asm.ClassVisitor java.lang.ClassLoader.defineClass(java.lang.ClassLoader.defineClass1(Native Method)java.lang.ClassLoader.defineClassCond(ClassLoader .java:637)在java.net.URLClassLoader.defineClass(URLClassLoader.java:283)上的java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)上的java.lang.ClassLoader.defineClass(ClassLoader.java:621) java.net.URLClassLoader.access $ 000(URLClassLoader.java:58)java.net.URLClassLoader $ 1.run(URLClassLoader.java:197)at java.security.AccessController.doPrivileged(Native Method)

每个unit testing。

根据Maven的依赖:树Robolectric和PowerMock不共享任何依赖关系。 显然org.powermock:powermock-module-javaagent封装了一些org / objectweb / asm类,而Robolectric依赖于org.ow2.asm:asm:jar:4.1导致冲突。


 @RunWith(RobolectricTestRunner.class) @PrepareForTest(Helper.class) @PowerMockIgnore({"com.sun.jmx.*", "javax.management.*"}) public class HelpFragTest { @Rule public PowerMockRule rule = new PowerMockRule(); static { PowerMockAgent.initializeIfNeeded(); } FragmentActivity fragmentActivity; FragmentManager fragmentManager; ActionBarManager actionBarManager; @Before public void setup(){ actionBarManager = mock(ActionBarManager.class); LowesApplication.instance().setActionBarManager(actionBarManager); fragmentActivity = Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get(); fragmentManager = fragmentActivity.getSupportFragmentManager(); } @Test public void testShow(){ mockStatic(Helper.class); HelpFrag helpFrag = HelpFrag.newInstance(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(helpFrag, null); fragmentTransaction.commit(); assertTrue(helpFrag.isVisible()); } } 

Solutions Collecting From Web of "使用PowerMock和Robolectric – IncompatibleClassChangeError"

我find了一个与Robolectric结合使用PowerMock的方法。

除了标准的PowerMockjar子之外,还需要PowerMock Junit Rule。 这里描述如何抓住它。 我使用了xstream类加载版本,因为objenesis是非常错误的。 这与PowerMock 1.5.5和Robolectric 2.3一起工作,我不能说老版本。 另请注意,不应该包含Java代理,因为从我的经验来看,它会导致问题。

所以,如果你正在使用maven,应该声明这些依赖关系:

 <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4-rule</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-classloading-xstream</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> 

然后你必须像这样设置你的testing类:

 @RunWith(RobolectricTestRunner.class) @PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" }) @PrepareForTest(Static.class) public class MyTest { @Rule public PowerMockRule rule = new PowerMockRule(); private MyActivity activity; @Before public void setup() { activity = Robolectric.buildActivity(MyActivity.class).create().get(); } @Test public void test() throws Exception { PowerMockito.mockStatic(Static.class); Mockito.when(Static.getCurrentTime()).thenReturn(1); Assert.assertEquals(1, activity.getId()); } }