Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use PowerMock in Android projects?

I created a new Android test project. I downloaded powermock-mockito-junit-1-1.5.zip from https://code.google.com/p/powermock/downloads/list. I added all of the libraries to the test project's libs folder. The test class is a very simple object:

package com.test.test;

import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;

import android.util.Log;

@RunWith(PowerMockRunner.class)
public class TestTestAndroid {

    public void testRuns() {
        Log.e("test", "Test case is called");
    }
}

Then, I try running the project from Eclipse, or making the project from the command line. I get the same error:

Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lorg/hamcrest/Description;

As it turns out, both junit-4.8.2.jar and mockito-all-1.9.5.jar define org.hamcrest.Description. I must include the Mockito jar for obvious reasons - I need Mockito. A different version of JUnit is provided by Android, but it is an old version that does not include the @RunWith annotation.

Can someone answer how to use powermock and mockito in an Android project, without the conflicting org.hamcrest.Description problem?

like image 323
Matt Quigley Avatar asked Mar 09 '13 00:03

Matt Quigley


2 Answers

Sorry, you can't use PowerMock in the Dalvik VM.

PowerMock works by running your test under a custom ClassLoader which uses Javassist to modify the bytecode of your classes. This works okay on a normal JVM, but on Dalvik the bytecode and class format are different, so this approach doesn't work. PowerMock would need to be rewritten to use Dexmaker instead of Javassist - this would be decidedly non-trivial, and I don't see anything like this on the PowerMock issues list.

like image 71
pobrelkey Avatar answered Sep 29 '22 18:09

pobrelkey


Actually, I find that this is completely untrue (at least with the latest version).

In my gradle setup for the module where I want to test my code I have

// Mockito and PowerMock
androidTestCompile ('org.powermock:powermock-mockito-release-full:1.6.0') {
    exclude module: 'hamcrest-core'
    exclude module: 'objenesis'
}

and everything runs fine. As long as I use:

@RunWith(PowerMockRunner.class) @PrepareForTest(ClassToMock.class)

to annotate my class (eg, can't run it with Robolectric, still fine in CI environments)

like image 45
AllDayAmazing Avatar answered Sep 29 '22 18:09

AllDayAmazing