第2章 第一个JUnit5测试用例:@Test注解、测试方法定义、断言基础、绿色/红色结果
2.1 原理概述
JUnit5 通过 @Test 注解将普通方法标记为可执行的测试用例。测试引擎在运行时会扫描被 @Test 修饰的方法,实例化测试类,依次执行这些方法,并收集执行结果。每个测试方法内部通过断言(Assertion)验证预期的行为,断言失败会抛出 AssertionError,测试用例标记为红色(失败);若所有断言通过且无未捕获异常,则标记为绿色(通过)。
关键概念: “绿色/红色结果” 源于测试运行器的 UI 反馈——绿色竖条表示全部通过,红色竖条表示存在失败用例,是 TDD(测试驱动开发)中快速定位问题的核心反馈信号。
2.2 实现流程
- 在
app/src/test目录(Android 单元测试源码集)下创建测试类,命名通常为XxxTest。 - 在测试类中定义
public、void的普通方法,方法名建议使用shouldXxx_whenYyy或testXxx模式。 - 在方法上方添加
@Test注解(来自org.junit.jupiter.api.Test)。 - 在方法体内调用被测试代码,并使用断言方法验证结果。
- 通过 Gradle 的
testDebugUnitTest任务或 IDE 的运行按钮执行测试,查看绿色/红色结果。
2.3 代码示例:第一个JUnit5测试用例
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
@Test
void shouldReturnSum_whenTwoPositiveNumbers() {
Calculator calc = new Calculator();
int actual = calc.add(3, 5);
assertEquals(8, actual, "3 + 5 应等于 8");
}
@Test
void shouldThrowException_whenDivideByZero() {
Calculator calc = new Calculator();
assertThrows(ArithmeticException.class,
() -> calc.divide(10, 0),
"除法分母为零应抛出算术异常");
}
}
方法可见性: JUnit5 的测试方法不强制
public,包级私有(default)即可。但为了统一风格,建议使用 void 且无参数,因为 JUnit5 不支持带参数的 @Test 方法(参数化测试需使用 @ParameterizedTest,后续章节涉及)。
2.4 断言基础:常用API对比
| 断言方法 | 用途 | 失败时消息 |
|---|---|---|
assertEquals(expected, actual) |
判断两个值相等(对对象调用 equals()) |
expected: <X> but was: <Y> |
assertNotEquals(unexpected, actual) |
判断两个值不相等 | expected: not equal but was: <Y> |
assertTrue(condition) |
判断条件为 true |
expected: <true> but was: <false> |
assertFalse(condition) |
判断条件为 false |
expected: <false> but was: <true> |
assertNull(object) |
判断对象为 null |
expected: <null> but was: <obj> |
assertNotNull(object) |
判断对象不为 null |
expected: not <null> |
assertThrows(exceptionType, executable) |
验证执行 Executable 时抛出了指定类型的异常 |
Expected ... to be thrown, but nothing was thrown. |
2.5 内联SVG:测试执行与结果判断流程
2.6 调试与常见错误
常见错误1: 误导入 JUnit4 的
@Test 注解(org.junit.Test),导致断言方法不兼容。应使用 org.junit.jupiter.api.Test 和 org.junit.jupiter.api.Assertions。
常见错误2: 测试方法带有参数,JUnit5 标准
@Test 方法必须无参数。若需要参数化,请使用 @ParameterizedTest(第6章介绍)。
常见错误3: 断言失败时消息字符串缺失或使用
System.out.println 检查结果。正确做法是通过断言方法的最后一个参数传入自定义失败消息,便于定位。
2.7 在 Android Studio 中查看绿色/红色结果
- 执行测试后,Run 窗口顶部显示绿色竖条(全部通过)或红色竖条(有失败)。
- 每个测试方法前有绿色对勾或红色叉号图标。
- 红色结果时,点击测试方法可查看堆栈跟踪,定位到断言失败的源代码行。
- Gradle 命令行执行
./gradlew testDebugUnitTest后,控制台输出BUILD SUCCESSFUL(绿色)或BUILD FAILED(红色),并在build/reports/tests/testDebugUnitTest/index.html生成 HTML 报告。
2.8 性能与稳定性提示
- 每个测试方法应保持独立、无顺序依赖,避免共享可变状态(参考第4章生命周期)。
- 断言数量适当,不推荐在单个测试中做上百个断言;若需验证复杂对象,使用
assertAll()分组(第3章)。 - 避免在
@Test方法内使用Thread.sleep()等待,应使用测试工具如Awaitility或CountDownLatch控制异步。