2

我正在使用 Powermock,但是当我运行 Eclemma 覆盖时,由于 EclEmma 的已知问题,Powermock 测试用例不会被考虑在最终分数中。

我在stackoverflow上搜索的解决方法和其他答案建议有:

@Rule
public PowerMockRule rule = new PowerMockRule();

static {
 PowerMockAgent.initializeIfNeeded();
}

然后添加像 powermock-module-javaagent、powermock-module-junit4-rule-agent 这样的 jars。

在我运行代码时执行此操作然后发现错误:

java.lang.VerifyError: Expecting a stackmap frame at branch target 7

对于这个答案,建议使用各种版本的 javassit。但我无法完成这项工作并得到同样的错误。

我的 pom.xml 看起来像:

<dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.6.1</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-module-javaagent</artifactId>
        <version>1.6.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.powermock</groupId>
      <artifactId>powermock-module-junit4-rule-agent</artifactId>
      <version>1.6.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.21.0-GA</version>
      <scope>test</scope>
    </dependency>

如何让 PowerMock 测试用例包含在最终 Eclemma 分数中?

4

2 回答 2

3

我最喜欢的非答案:不要浪费时间尝试。

相反,将此作为不应使用 PowerMock的另一个提示;并花时间和精力学习如何编写更好的生产代码,无需 PowerMock 即可进行测试。

例如,开始查看这些视频;了解避免调用staticnew(以不可测试的方式)的代码通常是糟糕的代码;并且改进此代码不仅可以帮助您摆脱 PowerMock,还可以改进您的所有产品。

如果你发现离开 PowerMock 很困难;我的建议:然后将您的测试放入两个存储桶中(一个用于那些真正使用 PowerMock 来完成只有 PowerMock 可以做的事情;另一个用于所有其他);并且只测量后一个的覆盖率。这也将打开一条“前进的道路”:只需避免将 PowerMock 用于您的任何新事物。相反,你可以求助于 mockito,它在过去几年里有了很大的改进;甚至允许你做一些事情(实验性地),比如覆盖 final 方法。

于 2017-03-03T07:40:54.147 回答
0

我想出了一个办法,可能不干净,但我认为它行得通。
所以问题陈述是如何让 Powermock 包含在 EclEmma 中?.
方法的第一个变化是迁移到 Eclemma 的 maven 方法,即jacoco
在转到答案之前,请随意浏览下面的链接:

Power mock with jacoco
Java Instrumentation Basic of Java Instrumentation

简而言之,jacoco 通过锁定来识别代码覆盖率/加载时更新字节码/检测类
并且 powermock 也为其工作锁定/更新字节码/检测类以使其正常运行,但它是从磁盘而不是内存中进行的。
因此,当 jacoco 给出覆盖范围时,powermock 类不会被覆盖,因为 powermock 从磁盘文件运行测试用例,并且 jacoco 不知道 powermock 在做什么。
因此,围绕它的工作是将 jacoco 检测的类存储在磁盘上,然后 powermock 通过这些类运行测试,这反过来会让 jacoco 知道测试正在运行并将它们包含在代码覆盖率中。
[请随时纠正我对此的理解]
所以最终的代码更改是:

    <dependency>
        <groupId>org.jacoco</groupId>
        <artifactId>org.jacoco.agent</artifactId>
        <version>0.7.7.201606060606</version>
        <classifier>runtime</classifier>
    </dependency>
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <version>3.6.1</version>
        <scope>test</scope>
    </dependency>

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <configuration>
                <excludes>
                 // files you want to exclude
                </excludes>
            </configuration>
            <executions>
                <execution>
                    <id>default-instrument</id>
                    <goals>
                        <goal>instrument</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-restore-instrumented-classes</id>
                    <goals>
                        <goal>restore-instrumented-classes</goal>
                    </goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>report</goal>
                    </goals>
                    <configuration>
                        <dataFile>${project.build.directory}/coverage.exec</dataFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <systemPropertyVariables>
                    <jacoco-agent.destfile>${project.build.directory}/coverage.exec</jacoco-agent.destfile>
                </systemPropertyVariables>
            </configuration>
        </plugin>
    </plugins>
</build>

运行后 -PcodeCoverage 为我解决了问题。

于 2017-03-06T09:03:38.123 回答