Jacoco离线模式结合Mockito @Spy无法统计单元测试覆盖率求助
Jacoco离线模式与Mockito @Spy注解的覆盖率问题
问题核心
Jacoco离线模式本身支持Mockito的@Spy注解,但你的代码写法和配置细节导致覆盖率无法被统计。
原因分析
- 注解混用与实例创建逻辑冲突:同时在
ServiceImpl上标注@Spy和@InjectMocks,Mockito优先创建的Spy代理可能未关联到Jacoco插装后的类。 - 重复初始化破坏插装状态:使用
@RunWith(MockitoJUnitRunner.class)后,又在@BeforeEach中调用MockitoAnnotations.initMocks(this),重复初始化会干扰Jacoco的插装类加载。 - 类加载顺序问题:Mockito创建Spy时,可能加载的是未被Jacoco插装的原始类,导致覆盖率数据无法收集。
解决方案
方案1:手动创建Spy实例
避免注解混用,手动基于真实插装类创建Spy:
@RunWith(MockitoJUnitRunner.class) class SampleTest { private ServiceImpl impl; @BeforeEach void initMock() { // 基于真实实例创建Spy,确保关联插装后的类 impl = Mockito.spy(new ServiceImpl()); } @Test void testWithException() throws Exception { impl.testExcep(); } }
方案2:修正注解与初始化逻辑
保留@Spy但移除重复初始化,直接初始化真实实例:
@RunWith(MockitoJUnitRunner.class) class SampleTest { // 直接初始化真实实例,由@Spy生成代理 @Spy private ServiceImpl impl = new ServiceImpl(); // 移除重复的MockitoAnnotations.initMocks(this) @Test void testWithException() throws Exception { impl.testExcep(); } }
方案3:优化Jacoco插件配置
确保插装与报告阶段的执行顺序正确:
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.6</version> <executions> <execution> <id>pre-test-instrument</id> <goals> <goal>instrument</goal> </goals> </execution> <execution> <id>post-test-process</id> <phase>test</phase> <goals> <goal>restore-instrumented-classes</goal> <goal>report</goal> </goals> <configuration> <dataFile>${project.build.directory}/jacoco.exec</dataFile> </configuration> </execution> </executions> <configuration> <includes>com/test/**/*.class</includes> </configuration> </plugin>
关键说明
Jacoco离线插装是在编译后修改class文件,只要测试中调用的是插装后的类实例,就能正常统计覆盖率。Mockito的@Spy本身不会阻碍Jacoco,但错误的实例创建方式会导致代理未插装的原始类,进而丢失覆盖率数据。
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

