鉴于Jacoco在“动态”检测时不能很好地与PowerMockito配合使用,我一直在尝试配置离线检测,希望这能为我提供适用于使用PowerMockito的类的单元测试覆盖率。
我已经设置了我的pom,但我的测试课程仍然保持0%的覆盖率。任何帮助都非常感激,因为它让我慢慢疯狂!
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mandy</groupId>
<artifactId>jacoco-test</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>jacoco-test Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<powermock.version>1.5.4</powermock.version>
<jacoco.version>0.7.1.201405082137</jacoco.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.agent</artifactId>
<classifier>runtime</classifier>
<version>${jacoco.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>instrument</id>
<phase>process-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>restore-report</id>
<phase>prepare-package</phase>
<goals>
<goal>restore-instrumented-classes</goal>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<!--<argLine>${argLine}</argLine>-->
<systemPropertyVariables>
<!-- JaCoCo runtime must know where to dump coverage: -->
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
<finalName>jacoco-test</finalName>
</build>
</project>
这是我的课程:
public class Utils {
private Utils() {
}
public static String say(String s) {
return "hello:"+s;
}
}
这是我的测试:
@RunWith(PowerMockRunner.class)
@PrepareOnlyThisForTest(Utils.class)
@PowerMockIgnore("org.jacoco.agent.rt.*")
public class UtilsTest {
@Test
public void testSay() throws Exception {
PowerMockito.mockStatic(Utils.class);
Mockito.when(Utils.say(Mockito.anyString())).thenReturn("hello:mandy");
assertEquals("hello:mandy", Utils.say("sid"));
}
}
我运行mvn clean install生成jacoco.exe
覆盖率报告(使用ant脚本从jacoco.exec生成): -
答案 0 :(得分:14)
这个pom对我有用:
<build>
<finalName>final-name</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.2.201409121644</version>
<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>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
请参阅this链接。
答案 1 :(得分:7)
I saw the same behavior, though after following the thread on the GitHub issue it seems to be fixed in 1.6.5, which proved true for me.
Hopefully this will save someone a headache later :).
Working configuration with:
I am not using offline instrumentation.
答案 2 :(得分:1)
我使用PowerMock的javaagent使其工作。 见这里:https://code.google.com/p/powermock/wiki/PowerMockAgent
删除@RunWith
注释,按照上面的链接中所述放置 PowerMockRule 。把它公之于众。
将以下行放在maven-surefire-plugin配置中:
-javaagent:${org.powermock:powermock-module-javaagent:jar}
(使用此处描述的技术:Can I use the path to a Maven dependency as a property?)
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow</groupId>
<artifactId>q2359872</artifactId>
<version>2.0-SNAPSHOT</version>
<name>q2359872</name>
<properties>
<!-- Must be listed in the dependencies section otherwise it will be null. -->
<my.lib>${org.jmockit:jmockit:jar}</my.lib>
</properties>
<dependencies>
<dependency>
<groupId>org.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
<build>
<defaultGoal>generate-sources</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Example usage: -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
<configuration>
<executable>echo</executable>
<arguments>
<argument>path to jar=</argument>
<argument>${org.jmockit:jmockit:jar}</argument>
<argument>my.lib=</argument>
<argument>${my.lib}</argument>
</arguments>
</configuration>
</plugin>
<!-- end of Example usage -->
</plugins>
</build>
</project>
答案 3 :(得分:1)
我也面临同样的问题。我能够部分生成报告。我已将这两个标签用于我的测试用例@RunWith(PowerMockRunner.class) @PrepareForTest({})。并且我没有为我使用上述标签的测试案例生成报告。但是对于其中一个测试用例,只有@RunWith(PowerMockRunner.class)这个标签。不知何故,报告是针对该案例生成的。而且我从未使用过离线仪器。当我尝试使用离线工具时,我收到错误,说该课程已经过检测。我尝试了各种方案,并遵循各种链接,但无法生成报告。最后根据上面的评论我将我的powermock版本从1.5.5升级到1.6.5,我能够生成报告。以下是我的 pom.xml 条目
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${basedir}/target/jacoco.exec</destFile>
<!--
Sets the name of the property containing the settings
for JaCoCo runtime agent.
-->
</configuration>
</execution>
<execution>
<!--<id>post-unit-test</id>
<phase>test</phase>-->
<id>default-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<dataFile>${basedir}/target/jacoco.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${basedir}/target/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
以下是我在 pom .xml中输入的maven-surefire-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine}</argLine>
<skipTests>false</skipTests>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
@ {argLine}已设为属性
<properties>
<argLine>-noverify -Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=512m</argLine>
</properties>
并将我的powermock版本从1.5.5升级到1.6.5 。最后,我可以在我的测试用例中看到我使用以下标记的类生成报告 @RunWith(PowerMockRunner.class)@PrepareForTest({})
答案 4 :(得分:1)
我尝试了以下软件的这些版本;他们一起工作,无需任何额外工作即可生成jacoco报告。我将gradle构建工具与powermock,mockito和wiremock一起使用。
powermock-api-mockito2:2.0.2
powermock-module-junit4:2.0.2
gradle 5.6.2
以上内容正确生成了jacoco覆盖率报告。
答案 5 :(得分:0)
我最终使用离线工具和Jacoco(类似于你所做的)与sonar一起使用,我能够从中获得覆盖率数据。
答案 6 :(得分:0)
我使用了Jacoco离线工具,并在执行测试恢复原始类之后,在#34; restore-instrumented-classes&#34;目标。我的JaCoCo配置如下所示:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>jacoco-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>*</exclude>
</excludes>
</configuration>
</plugin>
答案 7 :(得分:0)
我和JaCoCo On-the-fly和PowerMock有同样的问题。每次都会生成0%的代码覆盖率
发现JaCoCo版本0.7.7.201606060606和PowerMock版本1.6.2兼容,并且代码覆盖率已成功生成。
答案 8 :(得分:0)
使用下面的maven插件代码片段,这在jenkins和本地工作正常,并显示PowermockRunner单元测试的完整代码覆盖率
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
</configuration>
</execution>
<execution>
<id>pre-integ-test</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<append>true</append>
</configuration>
</execution>
<execution>
<id>jacoco-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>jacoco-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
答案 9 :(得分:0)
对我来说,Offline Instrumentation的示例效果很好。
但就我而言,有一个更简单的解决方案:只是在声明之前,不要在@PrepareForTest({})批注中包含经过测试的类。
答案 10 :(得分:0)
Code Coverage with JaCoCo解释了原因
使用JaCoCo的最简单方法是-使用JaCoCo Java Agent进行即时检测。在这种情况下,加载类时会对其进行修改。您可以只使用JaCoCo代理运行应用程序,然后计算代码覆盖率。 Eclemma和Intellij Idea使用这种方式。但是有一个大问题。 PowerMock乐器类也有。 Javassist用于修改类。主要问题是Javassist从磁盘读取类,而所有JaCoCo更改都消失了。结果,PowerMock类加载器加载了巫婆类的零代码覆盖率。
我们将用ByteBuddy(#727)替换Javassist,它将帮助解决这个老问题。但是,现在无法将PowerMock与JaCoCo即时仪器一起使用。而且没有解决方法可以在IDE中获得代码覆盖。
JaCoCo Offline Instrumentation可以解决此问题。 Offline Instrumentation的示例解决了我的问题。
答案 11 :(得分:0)
该报告是正确的。当您模拟调用方法“ say”时发生的情况时,提供的测试不会导致任何覆盖。永远不要嘲笑“被测实例/类”,只能针对测试对象的依赖关系和环境进行模拟。
在这种情况下:测试永远不会到达代码return "hello:"+s;
,并且不会调用Utils的构造函数。没有覆盖率显示,因为这些行根本没有测试覆盖率。
尽管如此,但同时使用JaCoCo和PowerMock并非易事。我目前也在寻找如何使其运行的方法。也许您提供的测试只是不幸地编写了,而JaCoCo已经可以正常工作了?