【问题标题】:PowerMock ECLEmma coverage issuePowerMock ECLemma 覆盖问题
【发布时间】:2014-06-15 07:19:49
【问题描述】:


我们在 JUnit 中使用 EasyMock 和 PowerMock。使用的覆盖工具是 ECLEmma。使用 EasyMock,它以绿色正确显示覆盖范围(如已覆盖)。但是,对于使用 PowerMock 进行单元测试的代码,覆盖率显示为红色(未覆盖)。在网上阅读过类似的问题。但是,只是想检查是否有解决方案。

谢谢
文卡特斯

【问题讨论】:

  • 把你的powermock测试逻辑放在测试包内的其他简单java类中,并从测试类中调用merhod,增加应用程序的代码覆盖率。

标签: java junit easymock


【解决方案1】:

是的,有一个解决方案:

首先你必须添加这个maven依赖:

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

然后,不要使用这个注解@RunWith(PowerMockRunner.class),只需像这样在Test类中添加一个@Rule:

public class Test {

   @Rule
   public PowerMockRule rule = new PowerMockRule();

您可以在此博客中找到更多信息Make EclEmma test coverage work with PowerMock

【讨论】:

【解决方案2】:

这是一个已知问题:https://github.com/jayway/powermock/issues/422

而且已经很久了,不会很快修复的。

我建议你改用eCobertura

【讨论】:

  • 在切换之前请注意 eCobertura 的限制:bitbucket.org/jmhofer/ecobertura/…
  • eCobertura 插件似乎不再维护
  • 为了解决这个问题,我最终将所有使用 PowerMocikito.staticMock 的测试拆分到单独的类文件中,这样覆盖问题就不会扩散到我的所有测试中。
【解决方案3】:

这在我的项目中的大多数情况下都有效:

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

删除/评论 @RunWith(PowerMockRunner.class) 并在您的类路径中添加 powermock-module-javaagent-1.6.5.jar 后包括以下导入:

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

现在右键单击->Coverage As->Coverage Configurations 并在 Arguments 中添加以下行:

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

点击应用->覆盖范围。

还要注意@Before 在这种情况下不起作用,因此您必须从标有@Before 的方法中添加标有@Test 的方法中的所有内容。

【讨论】:

    【解决方案4】:

    我们有一个要模拟的静态类。使用模拟静态类,eclEmma 代码覆盖率插件在 Eclipse 中不起作用。所以我们所做的是,所以将 @RunWith(JUnit4.class) (而不是 @RunWith(PowerMockRunner.class) )放在类之前,并将以下几行放在类中

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

    编译类并运行测试类。代码覆盖率适用于课堂。此更改仅在 Eclipse IDE 中。

    编写测试用例后,我们将代码恢复正常。放置 @RunWith(PowerMockRunner.class) 而不是 @RunWith(JUnit4.class) 并在静态代码和 powermockrule 行上方注释。

    【讨论】:

      【解决方案5】:

      我已经设法使用 powermock-module-javaagent 使用 Jacoco 生成 PowerMock 覆盖范围。

      只需确保将 powermock 代理放在 jacoco 代理之后:

      <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>
      ...
      

      如果你想看一个例子,看看这个项目:https://github.com/jfcorugedo/sonar-scanner

      在这里您可以看到声纳考虑了静态方法和被 PowerMock 模拟的 new 语句:

      如果您想模拟 newstatements,请确保使用 PowerMockRule 而不是 PowerMockRunner

      看看this test

      【讨论】:

        【解决方案6】:

        更新 powermock 版本修复我的问题是支持版本的 maven 依赖

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

        希望对你有帮助!!!

        【讨论】:

          【解决方案7】:

          我遇到了同样的问题。所以,我更新了 powerMockito 版本。现在我使用的是 Power mock 1.7.4 版和 Jacoco 0.8.5 版。它甚至也在 eclipse 上工作。

          【讨论】:

            【解决方案8】:

            这里有一些更详细的全班答案。

            需要注意的几点:

            1. 我必须使用spy 而不是mockStatic

            2. 我不得不将@PrepareForTest 移到方法级别。

            3. 正如其他答案中提到的那样,我还必须添加以下依赖项

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

            以下是我的完整课程代码供参考:

            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);
                }
            }
            

            我希望这对某人有所帮助。

            【讨论】:

              【解决方案9】:

              对于模拟静态类,使用 @RunWith(PowerMockRunner.class) 并在 Eclipse 上运行“Coverage As JUnit 测试”确实会显示已覆盖的代码未覆盖,这显然是个问题。

              要添加到上面的解决方案,在一个maven项目中,你可以试试这个..

              在根pom.xml 中,为生成报告,添加html 作为cobertura-maven-plugin 中的格式。下面是它的外观。

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

              然后,转到您的类所在的模块并在 Eclipse Web 浏览器或您选择的一个中打开 target/site/cobertura/index.html 文件。您可以在那里找到覆盖范围信息。

              【讨论】:

              • 能否指导一下“Emma”代码覆盖率工具?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-12-02
              • 1970-01-01
              • 2016-09-09
              • 2012-03-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多