断言详解:让断言更易读
断言是测试的核心——测试能不能发现问题,全靠断言写得准不准。
JUnit 5 自带的断言够用,但 AssertJ 的链式断言写起来更顺滑。
JUnit 5 内置断言
基本断言
java
assertEquals(4, 2 + 2); // 相等
assertNotEquals(5, 2 + 2); // 不等
assertTrue(3 > 2); // 为真
assertFalse(3 < 2); // 为假
assertNull(object); // 为 null
assertNotNull(object); // 非 null
assertSame(a, b); // 同一引用
assertNotSame(a, b); // 不同引用数组断言
java
@Test
void testArray() {
int[] expected = {1, 2, 3};
int[] actual = {1, 2, 3};
assertArrayEquals(expected, actual);
}异常断言
java
@Test
void testException() {
assertThrows(NullPointerException.class, () -> {
String str = null;
str.length();
});
}超时断言
java
@Test
void testTimeout() {
assertTimeout(Duration.ofSeconds(1), () -> {
Thread.sleep(100);
});
}组合断言 assertAll
一次验证多个条件,全部通过才算成功:
java
@Test
void testGroupedAssertions() {
assertAll("用户信息",
() -> assertEquals("张三", user.getName()),
() -> assertEquals(25, user.getAge()),
() -> assertTrue(user.isActive()),
() -> assertNotNull(user.getEmail())
);
}AssertJ:链式断言
AssertJ 是 JUnit 5 断言的首选,链式写法更易读:
对象断言
java
assertThat(user)
.isNotNull()
.hasName("张三")
.hasAge(25)
.extracting(User::getEmail)
.isNotBlank();集合断言
java
assertThat(users)
.isNotEmpty()
.hasSize(3)
.extracting(User::getName)
.containsExactly("张三", "李四", "王五")
.allMatch(name -> name.length() > 0); // 全部满足条件异常断言
java
@Test
void testExceptionWithAssertJ() {
assertThatThrownBy(() -> {
throw new IllegalArgumentException("参数错误: id=123");
})
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("参数错误")
.hasMessageContaining("123");
}软断言 softAssertions
即使一个断言失败,后面的断言仍然会执行:
java
@Test
void testSoftAssertions() {
SoftAssertions softly = new SoftAssertions();
softly.assertThat(user.getName())
.isEqualTo("张三");
softly.assertThat(user.getAge())
.isEqualTo(25);
softly.assertThat(user.getEmail())
.isNotBlank();
softly.assertAll(); // 统一报告所有失败
}断言选择建议
| 场景 | 推荐 |
|---|---|
| 简单值比较 | JUnit 5 assertEquals |
| 复杂对象 | AssertJ |
| 多个条件组合 | assertAll 或 SoftAssertions |
| 异常验证 | AssertJ assertThatThrownBy |
| 集合操作 | AssertJ |
总结
断言的写法直接影响测试的可读性和维护性:
- 选对工具:AssertJ 的链式断言比 JUnit 原生更易读
- 一个断言测一件事:别在一个 assert 里塞太多条件
- 失败消息要清楚:用
assertEquals(expected, actual, "失败原因")或 AssertJ 的as()方法
断言是测试的眼睛,断言写得烂,问题发现不了。
