2013-12-13 9 views
16

私はAndroid Robolectricテストでいくつかの静的メソッドをモックするためにPowerMockitoを使用しようとしています。私は、JUnit 4.8.2、Robolectric 2.2、Mockito 1.9.5、およびPowerMock 1.9.5を指示通りhereとして使用しています。 RoboElectricTestRunnerを使用する必要があるため、PowerMockRuleを使用してPowerMockをブートしようとしています。しかし、PowerMockを使ったテストが実行されると、私は残念なことにjava.lang.IncompatibleClassChangeErrorになります。PowerMockとRobolectricを使用する - IncompatibleClassChangeError

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)

私は私が手org.powermockライブラリの後org.ow2.asmを置く場合:

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.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method)

すべてのユニットテスト。

Maven depencyによると、ツリーRobolectricとPowerMockは依存関係を共有しません。 しかし明らかorg.powermock:powermockモジュール-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()); 
    } 
} 
+0

パワーモックランナー。だからRobolectricテストランナーで実行しようとすると意味がありません –

+2

@EugenMartynovそれはjavaagentと 'PowerMockRule'が解決しようとしている問題です。[PowerMockRule](http://code.google.com/ p/powermock/wiki/PowerMockRule)と[PowerMockAgent](http://code.google.com/p/powermock/wiki/PowerMockAgent)を参照してください。 –

+0

これは私たちのためにも問題であるので、あなたがそれを解決すれば、私に知らせてください。 –

答えて

9

私はRobolectricと一緒にPowerMockを使用する方法を発見しました。

標準のPowerMock jarに加えて、PowerMockのJunitルールも必要です。それはそれをつかむ方法を記述されているhereobjenesisは非常にバグが多いので、私はxstreamクラスローディングバージョンを使用しました。これは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> 

次に、あなたはこのようにセットアップするために、あなたのテストクラスがあります。それを実行するためにあなたが持っているパワーモックを使用するには

@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()); 
    } 
} 
+0

私はこのメソッドを使って作業しましたが、それは関連するAndroidの問題に投稿されました。RobolectricクラスローダーとPowermockクラスローダーの間で競合するものにぴったりでした。 –

+0

これは私のために働いた!ありがとう:) –

+0

Robolectricが正しく影に読み込まれていないかもしれないことに注意してください。これは私が現在この設定で経験しているものです –

関連する問題