学java单元测试需踩准节奏:先建立“测什么、为什么测”直觉,再用junit 5自动化;强调快、独立、确定性;融入tdd、mock隔离、参数化等实用技能。

从零开始学 Java 单元测试,关键不是堆时间,而是踩准节奏:先建立“测什么、为什么测”的直觉,再用 JUnit 把它自动化、结构化。不需要等代码写完才开始,越早动手,越容易形成肌肉记忆。
第一阶段:理解单元测试的底层逻辑
别急着写@Test,先搞清三个问题:
- 测什么?最小可独立验证的单元——通常是一个 public 方法(比如计算价格、校验用户名、转换日期格式);不是整个类,更不是页面交互。
- 为什么测?不是为了应付流程,而是为了:改代码时不心慌(重构有保障)、加功能时有依据(新逻辑是否破坏旧逻辑一目了然)、新人接手时能看懂你写的代码想干什么(测试就是活文档)。
- 好测试长什么样?满足三个词:快(毫秒级)、独立(不依赖数据库、网络、其他测试)、确定(同一输入永远得同一输出,不随机、不时序敏感)。
第二阶段:用 JUnit 写出第一个真正可用的测试
跳过老版本(JUnit 4),直接上 JUnit 5(当前主流,语法更干净,支持现代 Java 特性):
- 在 Maven 项目中加依赖:
<dependency><groupid>org.junit.jupiter</groupid><artifactid>junit-jupiter</artifactid><version>5.10.2</version><scope>test</scope></dependency> - 写一个被测类(比如一个简单计算器):
public int multiply(int a, int b) { return a * b; } - 写测试类(注意命名规范,如
CalculatorTest):
用@Test标记方法,用Assertions.assertEquals(6, calc.multiply(2, 3));验证结果;
用@Test+expected = ArithmeticException.class测试异常场景;
用@Test+timeout = 100防止方法卡死。
第三阶段:让测试真正支撑日常开发
光会断言不够,要融入真实工作流:
-
测试命名要有信息量:不用
test1(),改用multiply_WhenBothPositive_ReturnsCorrectProduct()—— 看名字就知道覆盖了什么场景。 - 每个测试只验证一件事:一个方法里别塞多个 assert;想测多种输入,就拆成多个@Test方法,失败时定位更快。
-
学会隔离外部依赖:当你的方法调用了数据库或 HTTP 接口,用 Mockito 创建 Mock 对象代替真实调用,比如
when(userService.findById(1L)).thenReturn(new User("Alice"));,这样测试不靠环境也能跑。 - 把测试变成日常习惯:写新功能前,先写一个让它失败的测试(TDD 小步走);修 Bug 时,先补一个复现 Bug 的测试,再改代码——确保它真被修好了,且不会复发。
第四阶段:进阶但不炫技的实用能力
掌握这些,你就已经比多数初级开发者更稳:
-
参数化测试:用
@ParameterizedTest+@ValueSource或@CsvSource,一套逻辑批量验证多组数据,避免重复写十几个相似的@Test。 -
生命周期控制:用
@BeforeEach做通用初始化(如新建对象),用@AfterEach清理资源(如关闭模拟的文件句柄),保持测试干净不污染。 -
分组执行:给测试打标签(
@Tag("fast")/@Tag("integration")),CI 构建时可快速跑核心单元测试,夜间再跑耗时长的全量集。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











