Spring Boot项目中Jacoco无法更新MockMvc测试的代码覆盖率问题
针对你遇到的Jacoco不统计MockMvc测试覆盖率的问题,结合你的代码和配置,我整理了几个关键排查点和解决方案:
1. 优先排查:请求路径是否真的命中Controller
你的测试请求路径是/gateway/v1/{thing}/{thing2},但看你给出的LegacyController的@GetMapping只有/{thing}/{thing2},如果你的Controller类上没有添加@RequestMapping("/gateway/v1")注解的话,这个请求根本没打到Controller方法里!这是最常见的导致覆盖率无变化的原因——测试看似通过,但实际没执行到目标代码。
解决:
- 确认Controller类上的@RequestMapping路径,确保测试的请求路径和Controller的路径完全匹配;
- 可以在Controller的
doSomeThing方法里加一行日志或者断点,验证测试是否真的进入了该方法。
2. 优化测试类的注解配置
你当前用了@SpringBootTest + @AutoConfigureMockMvc + @WebAppConfiguration,这种全量上下文启动的方式不仅重,还可能导致Jacoco统计异常。推荐用专门针对Controller层的@WebMvcTest注解:
修改后的测试类:
@RunWith(SpringRunner.class) @WebMvcTest(LegacyController.class) // 仅加载Controller相关的上下文 @ActiveProfiles("test") public class LegacyControllerTest { @Autowired private MockMvc mockMvc; // 自动配置好的MockMvc,无需手动初始化 @MockBean private LegacyService legacyService; @Test public void givenGetJson_WhenOffsetPageIsPresent_ThenReturnsCreated() throws Exception { Mockito.doReturn(new ResponseEntity<>("OK", HttpStatus.CREATED)) .when(legacyService).crud( Mockito.anyString(), Mockito.anyString(), Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.any(), Mockito.anyString() ); mockMvc.perform(MockMvcRequestBuilders .get("/gateway/v1/{thing}/{thing2}", "value-thing", "value-thing2") .header("Content-Type", "application/json") .header("Header1", "Header1 value") .queryParam("OtherThing", "OtherThing value") .queryParam("OtherThing2", "OtherThing2 Value") .content("A BODY GOES HERE")) .andDo(MockMvcResultHandlers.print()) .andExpect(MockMvcResultMatchers.status().isCreated()); // 注意Controller标注的是CREATED而非OK } }
另外注意:你的Controller方法标注了@ResponseStatus(value = HttpStatus.CREATED),所以测试里的isOk()应该改成isCreated(),避免逻辑不一致。
3. 检查Jacoco插件的执行配置
你的Jacoco配置里,prepare-agent没有指定执行阶段,可能导致测试运行时代理没生效,无法生成覆盖率数据:
修改Jacoco插件的executions配置,明确绑定阶段并升级到稳定版:
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.10</version> <!-- 升级到最新稳定版,兼容性更好 --> <configuration> <excludes> <exclude>**/constant/*</exclude> <exclude>**/dto/*</exclude> <exclude>**/enuns/*</exclude> <exclude>**/exception/*</exclude> <exclude>**/ApiApplication.class</exclude> </excludes> </configuration> <executions> <execution> <id>jacoco-prepare-agent</id> <phase>process-test-classes</phase> <!-- 明确在测试类处理后执行 --> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>generate-code-coverage-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin>
4. 验证覆盖率数据文件是否生成
运行mvn clean test后,检查target目录下是否生成了jacoco.exec文件:
- 如果没有,说明Jacoco的prepare-agent没生效,需要检查Maven插件的执行顺序,或者有没有其他插件干扰了Jacoco的代理;
- 如果有,再运行
mvn jacoco:report,然后查看target/site/jacoco下的HTML报告,确认是否有LegacyController的统计数据。
5. 排除其他可能的干扰
- 确认你的Maven命令是正确的:推荐用
mvn clean verify,这个命令会自动运行测试并生成覆盖率报告; - 检查Jacoco的exclude规则,确保没有误排除LegacyController所在的包;
- 如果你用了Lombok,确保Jacoco能正确处理Lombok生成的代码(你的Spring Boot插件已经排除了Lombok,这部分没问题)。
内容的提问来源于stack exchange,提问作者Vitor

