1

I'm trying to use PowerMock in my unit test (JUnit 4.12).

I already have Mockito integrated without any issue. This is an Android application.

When I run my unit test, no problem and the mocking of the static function works perfectly.

When I click on the "play" button in eclipse to run my app on the physical machine connected, I receive this error:

[2015-01-15 15:22:22 - Dex Loader] Unable to execute dex: Multiple dex files define Lorg/hamcrest/Description;
[2015-01-15 15:22:22 - CLAP] Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lorg/hamcrest/Description;

I have read that this means that PowerMock doesn't support the Delvik VM but I don't understand what this means and I can't believe that the PowerMock team or Mockito Team did not find a way to work in the Android environment!

Here is my dependencies in Maven related to PowerMock and Mockito

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
        </dependency>

       <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-module-junit4</artifactId>
          <version>1.6.1</version>
          <scope>test</scope>
       </dependency>

       <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-api-mockito</artifactId>
          <version>1.6.1</version>
          <scope>test</scope>
       </dependency>

Can anybody help me?

EDIT

I'm pretty sure all I need to do is to remove the PowerMock from my dependencies when I run my application for real (not in test) but I don't know how to do this. I'm using Eclipse so I need a solution that will work in this environment. I have checked the Profile and Exclusion from Maven but I can't see how to achieve this. I'm very new to maven. Any help will be greatly appreciated.

Also, when I remove the PowerMock dependencies (and all the unit test using it), the project now is able to run on my device without problem.

EDIT 2

With the help of the command mvn dependency:list suggested in the comment, I have discovered this:

  • JUnit have a dependency on org.hamcrest:hamcrest-core:jar:1.3:test
  • PowerMock have also a dependency on the hamcrest library

It seems the problem is only happening when it's the hamcrest version of the library that is used in the project. I have tried to remove JUnit dependency and only use the powermock one and the error at launch is the same. So I don't think it's a "collision" problem but maybe a problem with the hamcrest version coming with powermock??? And I wonder why it's using at launch since it's in the "test" scope...

EDIT 3 I have created a Android project from scratch with Maven to see if it's a problem with my main application or with Maven. The problem seems to be in Maven OR in the PowerMock dependency. If you want to try, here is the complete java project. There is no unit test in this project, I only want to run it on my Android machine. I still receive the exact same message.

Jean-François Côté
  • 4,200
  • 11
  • 52
  • 88
  • Is this instrumental or robolectric test? – Eugen Martynov Jan 16 '15 at 11:38
  • Do you see harmcrest duplicated dependency if you run in console `mvn -o dependency:list \ | grep ":.*:.*:.*" \ | cut -d] -f2- \ | sed 's/:[a-z]*$//g' \ | sort -u ` – Eugen Martynov Jan 16 '15 at 11:41
  • This is an android app. I use unit test (on the windows machine). When I run the app, it's runned on a android device. So I guess it's not instrumental or roblectric test (don't know what this is) – Jean-François Côté Jan 16 '15 at 13:54
  • I wasn't able to run your command, I receive this message: grep: : Invalid request code cut: : Invalid request code sed: read error on : Invalid request code – Jean-François Côté Jan 16 '15 at 14:26
  • That is instrumental tests and didn't know you're on windows. Just run `mvn dependency:list` and check if there are `Hamcrest` dependency – Eugen Martynov Jan 16 '15 at 16:07
  • `Powermock` is already part of you `test` scope. So if should not be present in the app. What I see that `Mockito` has default scope, so it means that you pack test library in production apk. I'm not sure if you build apk with maven or eclipse – Eugen Martynov Jan 18 '15 at 16:30
  • @EugenMartynov, Just updated my question with Edit 2. Maybe you will see the problem??? – Jean-François Côté Jan 19 '15 at 18:27
  • I'm still in doubts where do you run your tests. JUnit 4 is not available for instrumental test unless you are using latest support test library from Google. How did you remove junit dependency? Did you run clean? Was project dependencies updates in eclipse project? I know that eclipse is not good with maven. The error clearly says that dex failed because you have multiple class definition – Eugen Martynov Jan 20 '15 at 09:15
  • @EugenMartynov , I have added a link to a complete empty project which does the problem. – Jean-François Côté Jan 22 '15 at 13:27
  • I downloaded sample, installed latest maven, updated to the latest android maven plugin, modified project structure because it was faster than specifying things in maven and I was able to build apk and install on the device – Eugen Martynov Jan 22 '15 at 13:45
  • It means that you don't use maven at all and you use pom.xml just for specifying dependencies. What is you m2 plugin version for eclipse? Give also screenshots for you project settings in eclipse where dependencies are specified – Eugen Martynov Jan 22 '15 at 13:47

1 Answers1

1

I have finally fixed the problem but I don't understand everything. Thanks a lot to Eugen Martynov for his help and to this post which point me in the right direction.

The problem seems to be that Maven have a big problem with duplicated .jar files that are in nested dependencies. By using the class search, I discovered that the hamcrest class name "Description" was in my project 3 times!

So I did some research on how to exclude dependencies in Maven and discover that you can do all of this in the Maven Pom Editor. You can click on a dependencies in the dependencies tab and do "Remove".

The rest of the problem was just to remove the duplicated Hamcrest dependencies to have only one in my project. After fixing this problem, a second library had the same problem "obgenesis". I did the same fix and it finally worked.

Eugen Martynov pointed out to me in the comment that I was not using Maven at all. Maybe that's true, bear with me! At least now, I know Maven a little bit more and it does what it needed to do in my project.

Here is the final dependencies code:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <exclusions>
        <exclusion>
            <artifactId>hamcrest-core</artifactId>
            <groupId>org.hamcrest</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.10.8</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <artifactId>objenesis</artifactId>
            <groupId>org.objenesis</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.6.1</version>
    <scope>test</scope>
    <optional>true</optional>
    <exclusions>
        <exclusion>
            <artifactId>junit</artifactId>
            <groupId>junit</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.1</version>
    <scope>test</scope>
    <optional>true</optional>
    <exclusions>
        <exclusion>
            <artifactId>mockito-all</artifactId>
            <groupId>org.mockito</groupId>
        </exclusion>
    </exclusions>
</dependency>
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Jean-François Côté
  • 4,200
  • 11
  • 52
  • 88
  • Good that you resolved it. Two comments: maven doesn't have problem with nested dependencies, it is just android build that is strict for duplicated dependencies; I encourage you to learn and use gradle (and Android Studio) since it is supported by Google, maven is not (and eclipse is not also soon) – Eugen Martynov Jan 22 '15 at 15:26
  • Thanks! Will look at this soon! – Jean-François Côté Jan 22 '15 at 15:31