我试图用PowerMockito嘲弄一些静态方法的Android Robolectric测试。我使用JUnit 4.8.2,Robolectric 2.2的Mockito 1.9.5和1.9.5 PowerMock作为导演的这里。当我不得不使用RoboElectricTestRunner,我试图使用 PowerMockRule 来引导PowerMock。但是我得到一个不幸的 java.lang.IncompatibleClassChangeError 测试与PowerMock运行时。
java.lang.reflect.InvocationTargetException 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在java.lang.reflect.Method.invoke(Method.java:597) 在sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323) 在sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:348)
致:java.lang.IncompatibleClassChangeError:实现类 在java.lang.ClassLoader.defineClass1(本机方法) 在java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) 在需要java.lang.ClassLoader.defineClass(ClassLoader.java:621) 在java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
如果我把 org.ow2.asm 的 org.powermock 库我收到后:
java.lang.IncompatibleClassChangeError:类org.objectweb.asm.tree.ClassNode有接口org.objectweb.asm.ClassVisitor作为超一流 在java.lang.ClassLoader.defineClass1(本机方法) 在java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) 在需要java.lang.ClassLoader.defineClass(ClassLoader.java:621) 在java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) 在java.URLClassLoader.defineClass(URLClassLoader.java:283) 在java.URLClassLoader.access $ 000(URLClassLoader.java:58) 在java.URLClassLoader的$ 1.运行(URLClassLoader.java:197) 在java.security.AccessController.doPrivileged(本机方法)
上的每次的单元测试。
据Maven的depency:树Robolectric和PowerMock不共享任何依赖关系。 但是显然 org.powermock:powermock模块-javaagent 包一些组织/ ObjectWeb的/ ASM 类和Robolectric依靠组织。 ow2.asm:ASM:罐子:4.1 发生冲突
@RunWith(RobolectricTestRunner.class) @ prepareForTest(Helper.class) @PowerMockIgnore({com.sun.jmx。*,javax.management。*}) 公共类HelpFragTest { @规则 公共PowerMockRule规则=新PowerMockRule(); 静态{ PowerMockAgent.initializeIfNeeded(); } FragmentActivity fragmentActivity; FragmentManager fragmentManager; ActionBarManager actionBarManager; @之前 公共无效设置(){ actionBarManager =模拟(ActionBarManager.class); 。LowesApplication.instance()setActionBarManager(actionBarManager); fragmentActivity = Robolectric.buildActivity(FragmentActivity.class).create()开始()恢复()得到()。; fragmentManager = fragmentActivity.getSupportFragmentManager(); } @测试 公共无效testShow(){ mockStatic(Helper.class); HelpFrag helpFrag = HelpFrag.newInstance(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(helpFrag,NULL); fragmentTransactionmit(); assertTrue(helpFrag.isVisible()); } }解决方案
我找到了一种方法来使用PowerMock结合Robolectric。
在除了标准PowerMock罐子,所述PowerMock Junit的规则也是需要的。它被描述这里如何抓住它。我使用了 XStream的类加载版本,因为 objenesis 一个是非常错误。这正与PowerMock 1.5.5和Robolectric 2.3,我不能谈论的旧版本。同时请注意,Java代理不应包括在内,因为从我的经验,它引起的问题。
所以,如果你使用maven,这些依赖应该声明:
<依赖> <的groupId> org.powermock< /的groupId> < artifactId的> powermock模块,junit4< / artifactId的> <版> $ {powermock.version}< /版本> <范围>测试< /范围> < /依赖性> <依赖> <的groupId> org.powermock< /的groupId> < artifactId的> powermock模块-junit4规则< / artifactId的> <版> $ {powermock.version}< /版本> <范围>测试< /范围> < /依赖性> <依赖> <的groupId> org.powermock< /的groupId> < artifactId的> powermock-API的Mockito< / artifactId的> <版> $ {powermock.version}< /版本> <范围>测试< /范围> < /依赖性> <依赖> <的groupId> org.powermock< /的groupId> < artifactId的> powermock-类加载-XStream的< / artifactId的> <版> $ {powermock.version}< /版本> <范围>测试< /范围> < /依赖性>
然后,你必须设置你的测试类是这样的:
@RunWith(RobolectricTestRunner.class) @PowerMockIgnore({org.mockito。*,org.robolectric。*,机器人。*}) @ prepareForTest(Static.class) 公共类MyTest的{ @规则 公共PowerMockRule规则=新PowerMockRule(); 私人MyActivity活动; @之前 公共无效设置(){ 活动= Robolectric.buildActivity(MyActivity.class).create()得到()。 } @测试 公共无效测试()抛出异常{ PowerMockito.mockStatic(Static.class); Mockito.when(Static.getCurrentTime())thenReturn(1)。 Assert.assertEquals(1,activity.getId()); } }I'm trying to use PowerMockito to mock some static methods in Android Robolectric tests. I'm using JUnit 4.8.2, Robolectric 2.2, Mockito 1.9.5, and PowerMock 1.9.5 as directed here. As I have to use the RoboElectricTestRunner, I'm attempting to use the PowerMockRule to bootstrap PowerMock. However I'm getting an unfortunate java.lang.IncompatibleClassChangeError when the test with PowerMock runs.
java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:323) at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:348)
Caused by: java.lang.IncompatibleClassChangeError: Implementing class at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) at java.lang.ClassLoader.defineClass(ClassLoader.java:621) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
If I put org.ow2.asm after the org.powermock libraries I get:
java.lang.IncompatibleClassChangeError: class org.objectweb.asm.tree.ClassNode has interface org.objectweb.asm.ClassVisitor as super class at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637) at java.lang.ClassLoader.defineClass(ClassLoader.java:621) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.URLClassLoader.defineClass(URLClassLoader.java:283) at java.URLClassLoader.access$000(URLClassLoader.java:58) at java.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method)
on every unit test.
According to Maven depency:tree Robolectric and PowerMock don't share any dependencies. But apparently org.powermock:powermock-module-javaagent packages some org/objectweb/asm classes, and Robolectric relies on org.ow2.asm:asm:jar:4.1 causing a conflict.
@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); fragmentTransactionmit(); assertTrue(helpFrag.isVisible()); } }解决方案
I found a way to use PowerMock in conjunction with Robolectric.
In addition to the standard PowerMock jars, the PowerMock Junit Rule is also needed. It is described here how to grab it. I used the xstream classloading version, because the objenesis one is very buggy. This is working with PowerMock 1.5.5 and Robolectric 2.3, i cannot speak about the older versions. Also please note that the Java agent should not be included, because from my experience it causes problems.
So if you are using maven, these dependencies should be declared:
<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>Then you have to setup your test class like this:
@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()); } }
更多推荐
使用PowerMock和Robolectric
发布评论