Make EclEmma test coverage work with PowerMock

EclEmma and Mockito do not work well together out-of-the-box. EclEmma report no coverage at all on test run with PowerMock runner. However there is a way to make it work together, using the PowerMock javaagent. To do this, don’t use the @RunWith(PowerMockRunner.class) annotation as you’re used to. Instead, use the standard JUnit Runner or your runner extending a JUnit one, and add this rule to all your test classes:

@Rule
public PowerMockRule rule = new PowerMockRule();

You will also need to add the 2 following jars to your classpath, as explained here:

  • powermock-module-javaagent
  • powermock-module-junit4-rule-agent

You can find then on the Maven repository: here and here.

Third step is to initialize the agent, add the following lines to all your test classes, or to you runner if you have one to add it only once:

static {
     PowerMockAgent.initializeIfNeeded();
 }

And finally last step: modify your launch configuration running your test to add the following option to the VM arguments:

-javaagent:libs/powermock-module-javaagent-1.6.0.jar

And you should be able to use the Coverage As for EclEmma and see you test coverage result!

16 thoughts on “Make EclEmma test coverage work with PowerMock

  1. Marcelo

    Hi! Thanks for your post.

    I’m in a project in which we’re using JSF, JUnit 4 and PowerMock to test objects like RequestContext, Faces Context, etc. (I’m very new to this last thing)

    After implementing PowerMock in my unit tests, I noticed Eclemma thew 0% coverage in tests ran with the PowerMock runner, as you said. I tried using eCoberture, but it’s old and doesn’t work well.

    I tried appyling your solution, but I had to do one more thing. Besides the java agent argument, I had to add “-noverify” to the VM arguments for the JUnit execution.

    Now, this doesn’t worry me too much because it’s just the configuration used for testing purposes, but I’m not entirely clear on what’s going on here.

    If I don’t add “-noverify”, I get errors like “java.lang.VerifyError: Expecting a stackmap frame at branch target 84”, and none of the tests run.

    Can you explain this behaviour? Is this wrong or dangerous?

    Thanks very much.

    Just for reference, libraries included are:
    – powermock-api-mockito-1.6.2.jar
    – powermock-mockito-release-full-1.6.2-full.jar
    – powermock-module-javaagent-1.6.2.jar
    – powermock-module-junit4-1.6.2.jar
    – powermock-module-junit4-rule-agent-1.6.2.jar
    – mockito-all-2.0.2-beta.jar

    Reply
    1. Guillaume Post author

      Hi Marcelo,

      In order to mock some complex behavior (static method, final field and so on…), PowerMock has to mess with the byte code at runtime. Since Java 7, and even more since Java 8, some byte code verification mechanism has been added, which explain the error. I wrote about it here. I’m not surprised you have to use the -Xverify:none option for an IBM JVM. For a Sun JVM, -XX:-UseSplitVerifier should be enough.

      Regards,
      Guillaume

      Reply
  2. Dinu

    @Before
    public void init() {
    MockitoAnnotations.initMocks(this);
    }

    the above piece of code is needed if you are using Annotation in your test class.

    Reply
  3. Philippe Asmar

    I have followed this tutorial but the coverage still shows 0%.
    I am using PowerMock + EasyMock
    Some of the functions i use are: EasyMock.expect(), EasyMock.replay(),EasyMock.verify()
    Any idea why this does not work for me?

    Reply
  4. Felix Mayer

    Doesn’t work for me, I get this in the JUnit view:
    `
    java.lang.VerifyError: Expecting a stackmap frame at branch target 53
    Exception Details:
    Location:
    com/homedepot/mm/sv/adms/bl/SupplierControllerTest.$jacocoInit()[Z @4: ifnonnull
    Reason:
    Expected stackmap frame at this location.
    Bytecode:
    0x0000000: b202 6559 c700 3157 b202 6b06 bd00 0459
    0x0000010: 0314 026c b802 7253 5904 1302 7353 5905
    0x0000020: 1100 dfb8 0227 535a b602 7757 0332 c002
    0x0000030: 7859 b302 65b0

    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at org.junit.internal.builders.SuiteMethodBuilder.hasSuiteMethod(SuiteMethodBuilder.java:20)
    at org.junit.internal.builders.SuiteMethodBuilder.runnerForClass(SuiteMethodBuilder.java:13)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    `

    Reply
  5. Pingback: Eclipse PowerMock coverage with ECLEmma - JavaTechji

  6. Pingback: How to mock Final classes and have code coverage - JavaTechji

  7. Crhistyan Silva

    This works for me! You saved my life. For reference I used this versions:

    Eclipse 2019-12 (4.14.0)
    Eclemma 3.1.3
    powermock-module-junit4-rule-agent-2.0.7.jar
    powermock-module-javaagent-2.0.7.jar

    Reply
  8. Pingback: testing - Cannot get 100% code coverage for static methods inside a final class Java | ITTone

Leave a Reply to Dinu Cancel reply