27


We are using EasyMock and PowerMock with JUnit. The coverage tool used is ECLEmma. With EasyMock, it shows the coverage properly in green (as covered). However, for the code that is unit tested with PowerMock, the coverage is shown in red (uncovered). Have read similar questions on the web. However, just wanted to check if there is a solution for this.

Thanks
Venkatesh

risingTide
  • 1,754
  • 7
  • 31
  • 60
venkatesh
  • 435
  • 1
  • 5
  • 9
  • Put your powermock test logic in other simple java class inside test package, and call the merhod from test class, it increase code coverage for your application. – vishal thakur Jul 25 '21 at 17:10

9 Answers9

15

Yes, there is a solution for this:

First you will have to add this maven dependency:

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4-rule-agent</artifactId>
  <version>1.6.4</version>
  <scope>test</scope>
</dependency>

Then, instead of using this annotation @RunWith(PowerMockRunner.class), just add a @Rule in the Test class like this:

public class Test {

   @Rule
   public PowerMockRule rule = new PowerMockRule();

you can find more in this blog Make EclEmma test coverage work with PowerMock

LimaNightHawk
  • 6,613
  • 3
  • 41
  • 60
Rodrigo Villalba Zayas
  • 5,326
  • 2
  • 23
  • 36
  • Could you please guide here ?https://stackoverflow.com/questions/52064126/powermock-emma-code-coverage-showing-0-for-private-static-methods-and-other – Jeff Cook Aug 28 '18 at 19:10
12

It's a known problem : https://github.com/jayway/powermock/issues/422

And it has been for a long time, it won't be fixed anytime soon.

I suggest you use eCobertura instead.

7

This has worked in most cases in my project:

@Rule
public PowerMockRule rule = new PowerMockRule();
static {
    PowerMockAgent.initializeIfNeeded();
}

Remove/Comment @RunWith(PowerMockRunner.class) & include following imports after adding powermock-module-javaagent-1.6.5.jar in your classpath:

import org.junit.Rule;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.powermock.modules.agent.PowerMockAgent;

Now right click->Coverage As->Coverage Configurations and add following lines in Arguments:

-ea -noverify -javaagent:path/to/powermock-module-javaagent-1.6.5.jar

Click Apply->Coverage.

Also note that @Before would not work in this case so you have to add all the stuffs in the methods marked with @Test from the method marked with @Before.

being_ethereal
  • 795
  • 7
  • 26
2

We have a static classes to mock. With mocking static classes, eclEmma code coverage plugin is not working in Eclipse. So what we did is, so placed @RunWith(JUnit4.class) (Instead of @RunWith(PowerMockRunner.class) ) before class and placed following lines inside class

static {
PowerMockAgent.initializeIfNeeded();
}

@Rule
public PowerMockRule rule = new PowerMockRule();

Compiled the class and ran the test class. Code coverage is working for class. This change is only in Eclipse IDE.

After writing test cases, we reverted code back to normal. Placed @RunWith(PowerMockRunner.class) instead of @RunWith(JUnit4.class) and commented above static code and powermockrule lines.

1

I have managed to generate PowerMock coverage with Jacoco, using powermock-module-javaagent.

Just make sure you put powermock agent after jacoco agent:

<artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <useSystemClassLoader>true</useSystemClassLoader>
                <argLine>${jacocoArgLine} -javaagent:${settings.localRepository}/org/powermock/powermock-module-javaagent/${powermock.version}/powermock-module-javaagent-${powermock.version}.jar -noverify</argLine>
...

If you want to see an example, take a look at this project: https://github.com/jfcorugedo/sonar-scanner

Here you can see that sonar takes into account static methods and new statements mocked by PowerMock:

enter image description here

If you want to mock newstatements make sure you use PowerMockRule instead of PowerMockRunner.

Take a look at this test

jfcorugedo
  • 9,793
  • 8
  • 39
  • 47
0

Updating powermock version fix my issue below is maven dependency of supported version

<dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-module-junit4-rule-agent</artifactId>
   <version>1.7.3</version>
   <scope>test</scope>
</dependency>

Hope this helps !!!

RBS
  • 207
  • 1
  • 11
0

I was facing the same issue. So, I updated the powerMockito version. Now I am using Power mock version 1.7.4 and Jacoco version 0.8.5. It's even working on eclipse also.

Rishi Raj Tandon
  • 642
  • 8
  • 15
0

Here is some more detailed answer with full class.

couple of points to note:

  1. I had to use spy instead of mockStatic

  2. I had to move @PrepareForTest to method level.

  3. As someone mentioned in other answers I also had to add following dependency

    org.powermock:powermock-module-junit4-rule-agent:2.0.9

Below is my full class code for reference:

import java.util.ArrayList;
import java.util.Arrays;

import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.agent.PowerMockAgent;
import org.powermock.modules.junit4.rule.PowerMockRule;

import org.opensource.dummy.config.DummyConfig;
import org.opensource.dummy.data.builder.DataBuilder;
import org.opensource.dummy.model.SampleRequest;
import org.opensource.dummy.model.SampleType;
import org.opensource.dummy.model.Item;
import org.opensource.dummy.model.RequestType;

@RunWith(JUnit4.class)
public class MockedDataSearchServiceHelperTest {

    static {
        PowerMockAgent.initializeIfNeeded();
    }

    @Rule
    public PowerMockRule rule = new PowerMockRule();

    @PrepareForTest({ DummyConfig.class })
    @SuppressWarnings("unchecked")
    @Test
    public void testSearchResponseValid() throws Exception {
        Item Item = DataBuilder.createItem("2024-01-24", "2024-12-25", "61ef8faebec3bb72fbcf336d", null);
        SampleRequest sampleRequest = DataBuilder.createSampleRequest(Arrays.asList(Item),
                DataBuilder.createDeliveryMetrics(1), null, RequestType.ITEM);

        BoolQueryBuilder boolQueryBuilder = DataSearchServiceHelper.createCustomQuery(sampleRequest, Item);

        SearchRequestBuilder searchRequestBuilder = PowerMockito.mock(SearchRequestBuilder.class);
        ActionFuture<SearchResponse> actionFuture = PowerMockito.mock(ActionFuture.class);

        Client client = PowerMockito.mock(Client.class);

        PowerMockito.spy(DummyConfig.class);
        PowerMockito.doReturn(client).when(DummyConfig.class, "getClient");

        Mockito.when(client
                .prepareSearch(new String[] { "dummy" }))
                .thenReturn(searchRequestBuilder);
        Mockito.when(searchRequestBuilder.setIndicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN))
                .thenReturn(searchRequestBuilder);
        Mockito.when(searchRequestBuilder.setQuery(Mockito.any(QueryBuilder.class))).thenReturn(searchRequestBuilder);

        Mockito.when(searchRequestBuilder.execute()).thenReturn(actionFuture);

        Mockito.when(actionFuture.actionGet()).thenReturn(new SearchResponse(null, null, 0, 0, 0, 0, null, null));

        SearchResponse searchResponse = DataSearchServiceHelper.getSearchResponse(
                new String[] { "dummy" },
                boolQueryBuilder, DataBuilder.createDeliveryMetrics(1), RequestType.ITEM);

        Assert.assertNotNull(searchResponse);
    }
}

I hope this helps to someone.

Bilbo Baggins
  • 2,899
  • 10
  • 52
  • 77
-2

For mocking static classes, using @RunWith(PowerMockRunner.class) and running the "Coverage As JUnit Test" on Eclipse does show covered code as uncovered and it clearly does seem like an issue.

To add to the solutions above, in a maven project, you can try this..

In the root pom.xml, for report generation, add html as a format in cobertura-maven-plugin. Below is the way it looks.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <configuration>
       <formats>
          <format>html</format>
          <format>xml</format>
       </formats>
    </configuration>
</plugin>

Then, go to the module where your class resides and open target/site/cobertura/index.html file in Eclipse Web Browser or in the one of your choice. You can find the coverage information there.

Saran
  • 1,253
  • 1
  • 9
  • 10