最近发现个 mvn test 执行时候的问题,研究了一下
现象:使用 jacoco 统计单元测试报告插件,在不执行 mvn clean,连续执行两次 mvn test 会报以下错误:
Cannot process instrumented class 某个类名. Please supply original non-instrumented classes.
插件配置如下:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<configuration>
<append>true</append>
</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>target/jacoco.exec</dataFile>
<outputDirectory>target/jacoco-report</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
原因:jacoco 的 instrument 会在 maven 生命周期的 process-classes 阶段编译好的代码打桩用于统计代码覆盖率,然后在 restore-instrumented-classes 恢复打桩前的代码,但是执行 mvn test 命令的时候不会走完所有的生命周期,而是走到 test 为止,而为 test 在 restore-instrumented-classes 之前,导致后续恢复步骤未执行,第二次 mvn test 时会重复打桩,引起报错。
完整的生命周期顺序是:
validate
initialize
generate-sources
process-sources
generate-resources
process-resources
compile
process-classes ............. (instrument 默认所属周期)
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources
test-compile
process-test-classes
test ........................ (mvn test 执行的截止周期)
prepare-package ............. (restore-instrumented-classes 默认所属周期)
package
pre-integration-test
integration-test
post-integration-test
verify
install
deploy
instrument 默认属于 process-classes,restore-instrumented-classes 默认属于 prepare-package,晚于 test 所以不会被执行。
解决办法:应该使用 mvn verify 替代 mvn test