本文目录导读:

- 案例一:基础分支覆盖(Branch Coverage)—— 最经典的“坑”
- 案例二:条件覆盖(Conditional Coverage)—— 短路运算的陷阱
- 案例三:Maven集成与构建门槛(CI/CD实战)
- 实战技巧(针对上述案例)
- 如果你想看真实项目截图效果
关于JaCoCo(Java Code Coverage)的案例,我无法提供真实的公司内部项目代码,但我可以为你构建几个经典的、具有代表性的模拟案例场景,这些场景涵盖了JaCoCo最常见的应用方式,你可以直接运行这些代码来观察覆盖率的变化。
以下是三个核心场景的实战案例:
基础分支覆盖(Branch Coverage)—— 最经典的“坑”
场景描述:checkAge 方法用于校验年龄,开发者认为写了一个完整的测试,但实际上漏掉了隐藏的分支。
代码准备:
public class AgeValidator {
public static String checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
} else if (age < 18) {
return "Minor";
} else if (age < 65) {
return "Adult";
} else {
return "Senior";
}
}
}
测试代码(故意不全面):
import org.junit.Test;
import static org.junit.Assert.*;
public class AgeValidatorTest {
@Test
public void testAdult() {
assertEquals("Adult", AgeValidator.checkAge(30));
}
@Test
public void testMinor() {
assertEquals("Minor", AgeValidator.checkAge(10));
}
}
JaCoCo分析结果:
- 行覆盖率(Line Coverage):可能达到 75%(4个return语句执行了3个)。
- 分支覆盖率(Branch Coverage):可能只有 50%(
age < 0的 True 分支和age < 65的 False 分支没走)。 - 如果CI配置了
<rule><element>BRANCH</element><limits><limit counter="BRANCH" value="COVEREDRATIO" minimum="0.80"/></limits></rule>,这个构建会失败。
改进建议:增加测试用例 AgeValidator.checkAge(-1)(抛异常)和 AgeValidator.checkAge(70)(Senior),覆盖率才会达标。
条件覆盖(Conditional Coverage)—— 短路运算的陷阱
场景描述:isValidUser 方法使用了 && 短路逻辑,测试只测了“正常通过”和“完全不通过”,忽略了中间的短路情况。
代码准备:
public class UserValidator {
public boolean isValidUser(String username, String password) {
return username != null && !username.isEmpty()
&& password != null && password.length() >= 8;
}
}
测试代码:
import org.junit.Test;
import static org.junit.Assert.*;
public class UserValidatorTest {
@Test
public void testValid() {
UserValidator validator = new UserValidator();
assertTrue(validator.isValidUser("john", "password123"));
}
@Test
public void testNullUsername() {
UserValidator validator = new UserValidator();
assertFalse(validator.isValidUser(null, "password123"));
}
}
JaCoCo分析结果:
- 行覆盖率:100%(单行代码全执行了)。
- 条件覆盖率(分支覆盖):50%,因为对于第一个条件
username != null,测试只覆盖了False(null)和True(非null);但对于第二个条件!username.isEmpty(),由于短路,null场景没走到那一步,导致该条件的 True 和 False 分支只覆盖了其中一个。 - 教训:行率100%不代表逻辑测试完善,JaCoCo红色菱形(分支/条件)会明确提示这里有问题。
Maven集成与构建门槛(CI/CD实战)
场景描述:在pom.xml中配置JaCoCo插件,并设定覆盖率红线(行覆盖率低于80%则构建失败)。
核心配置(pom.xml 片段):
<build>
<plugins>
<!-- JaCoCo Maven Plugin -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal> <!-- 生成覆盖率数据文件 -->
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal> <!-- 生成HTML报告 -->
</goals>
</execution>
<execution>
<id>check</id>
<phase>verify</phase>
<goals>
<goal>check</goal> <!-- 执行覆盖率检查 -->
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum> <!-- 行覆盖不低于80% -->
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.70</minimum> <!-- 分支覆盖不低于70% -->
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
执行命令:
mvn clean verify
案例效果:
- 运行测试后,在
target/site/jacoco/index.html生成报告(红色/绿色/黄色的类)。 - 如果测试覆盖率不达标,
verify阶段直接BUILD FAILURE,阻止CI发布。
实战技巧(针对上述案例)
- 查看报告:打开
target/site/jacoco/index.html,点击具体的类。- 绿色:已覆盖。
- 红色:未覆盖的行。
- 黄色/菱形:部分覆盖的分支(需要双击查看具体是哪个条件没测到)。
- 故意漏测:尝试注释掉某个测试方法,再跑一次
mvn test,观察覆盖率数值变化,理解测试对覆盖率的贡献。
如果你想看真实项目截图效果
你可以快速在本地跑一个 Spring Boot 项目,添加 spring-boot-starter-test(自带JaCoCo),然后故意不写某个Service的测试,生成报告后你会看到:
- DAO/Mapper 层(接口)通常覆盖率为0%。
- Controller 层如果没有集成测试,覆盖率为0%。
- Service 层如果只测了主流程,分支覆盖率会亮红灯。
如果你需要,我可以为你生成一份具体的HTML报告截图样张(模拟数据),或者帮你写一个多模块项目的集成配置,你想深入哪个部分?