问题背景

多个项目组反应本地IDEA和jenkins运用Jacoco检测代码覆盖率时,测试类在有测试代码覆盖的前提下,显示覆盖率为0。

原理分析

JaCoCo支持两种方式检测覆盖率:a)在使用Java代理时动态进行;b)在构建阶段准备类时,脱机进行离线操作。
使用JaCoCo Java Agent进行即时检测,加载类时会对其进行修改。但PowerMock内部是从磁盘读取类,则所有JaCoCo更改都会消失。导致PowerMock的零覆盖率。
使用离线Instrumentation。修改后的类存储在磁盘上,可以实现覆盖率检测。但需更改构建过程,并且只能从构建工具maven运行测试才能收集代码覆盖率。(不建议)

解决方案

编写BaseRuleMock基类

1
2
3
4
5
6
7
8
public class BaseRuleMock{
@Rule
public PowerMockRule rule = new PowerMockRule();

static{
PowerMockAgent.initializeIfNeeded();
}
}

继承BaseRuleMock基类,去掉原有@RunWith(PowerMockRunner.class)注解

1
2
3
4
5
6
7
8
9
10
11
12
@PrepareForTest({UploadUtil.class})
public class XxxxTest extends BaseRuleMock{
@InjectMocks
private AxxxManager axxxManager;
@Mock
private AxxxMapper axxxMapper;
@Test
public void MethodTest{
...
}
...
}

在maven-surefire-plugin添加如下配置,取消校验

1
2
3
4
5
6
7
8
9
10
11
<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <version>2.18.1</version>
   <configuration>
<argLine>
<!-- jdk7则需改成-XX:-UseSplitVerifier -->
-noverify ${maven.test.jvmArgs}
</argLine>
   </configuration>
</plugin>

集成jenkins

效果展示

####IDEA

####JENKINS