1. JUnit单元测试基础与BMI计算器实战
第一次接触JUnit时,我盯着那些@Test注解发懵——直到把BMI计算器的算法拆解成测试用例才恍然大悟。单元测试就像给代码做"体检",而JUnit就是最趁手的检查仪器。先看这个简单的BMI分类逻辑:
public String getBMIType() { if(bmi<18.5) return "偏瘦"; else if(bmi<24) return "正常"; else if(bmi<28) return "偏胖"; else return "肥胖"; }1.1 测试环境搭建的坑与经验
在Eclipse里新建JUnit测试类时,我遇到过两个典型问题:
- 忘记添加JUnit库依赖,导致@Test注解报红
- 测试类和方法没有用public修饰,运行按钮是灰色的
正确姿势是用Maven管理依赖:
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency>1.2 第一个有效测试用例
给"偏瘦"分类写测试时,我最初直接写死了身高体重:
@Test void testThin() { BMI bmi = new BMI(45, 1.6); assertEquals("偏瘦", bmi.getBMIType()); }后来发现更好的做法是用边界值:
@Test void testThinBoundary() { // 18.5的边界值:1.6m身高对应47.36kg BMI bmi = new BMI(47.35, 1.6); assertEquals("偏瘦", bmi.getBMIType()); }2. 企业级测试策略设计
在电商项目踩过坑后,我总结出测试用例设计的"三明治法则":
2.1 黑盒测试方法实战
等价类划分示例(BMI场景):
| 分类 | 输入范围 | 有效等价类 | 无效等价类 |
|---|---|---|---|
| 偏瘦 | <18.5 | 17.5 | -1 |
| 正常 | 18.5~24 | 20 | 0 |
| 偏胖 | 24~28 | 26 | 身高为负数 |
边界值分析的经典场景:
@ParameterizedTest @ValueSource(doubles = {17.9, 18.4, 18.5, 23.9, 24.0, 27.9, 28.0}) void testBoundaries(double bmiValue) { BMI bmi = new BMI(); bmi.setBMI(bmiValue); assertNotNull(bmi.getBMIType()); }2.2 测试生命周期管理
在物流系统中,我用@BeforeEach初始化运单号生成器:
class WaybillTest { private WaybillGenerator generator; @BeforeEach void init() { generator = new WaybillGenerator(); generator.setPrefix("SF"); } @Test void generateId() { String id = generator.generate(); assertTrue(id.startsWith("SF2023")); } }3. 高级测试技巧与异常处理
支付模块的测试让我深刻认识到异常处理的重要性...
3.1 参数化测试进阶
用CSV文件管理测试数据:
@ParameterizedTest @CsvFileSource(resources = "/bmi_testcases.csv") void testWithCsv(double weight, double height, String expected) { BMI bmi = new BMI(weight, height); assertEquals(expected, bmi.getBMIType()); }bmi_testcases.csv示例:
45,1.6,偏瘦 55,1.6,正常 68,1.6,偏胖 80,1.6,肥胖 0,1.6,无效输入3.2 超时与并发测试
测试缓存服务时这样验证性能:
@Test @Timeout(5) void cacheResponseUnderLoad() throws Exception { ExecutorService pool = Executors.newFixedThreadPool(10); for(int i=0; i<100; i++) { pool.submit(() -> { assertNotNull(cache.get("key")); }); } pool.shutdown(); assertTrue(pool.awaitTermination(10, SECONDS)); }4. 企业级集成实践
在CI流水线中,我们这样配置Maven插件:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0</version> <configuration> <includes> <include>**/*Test.java</include> </includes> <excludes> <exclude>**/StressTest.java</exclude> </excludes> </configuration> </plugin>4.1 测试报告优化
使用Allure生成可视化报告:
<dependency> <groupId>io.qameta.allure</groupId> <artifactId>allure-junit5</artifactId> <version>2.13.0</version> </dependency>关键注解示例:
@Epic("健康管理") @Feature("BMI计算") @Story("用户BMI分类") @Test void shouldReturnObeseWhenBMIOver28() { // ... }4.2 测试覆盖率控制
JaCoCo配置阈值示例:
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> <executions> <execution> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>check-coverage</id> <goals> <goal>check</goal> </goals> <configuration> <rules> <rule> <limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>0.8</minimum> </limit> </rule> </rules> </configuration> </execution> </executions> </plugin>