1. 概述
本教程将带你一步步创建自定义的 AssertJ 断言。AssertJ 的基础知识可以参考这里。
简单说,自定义断言能让你为特定类创建专属断言方法,使测试代码更贴近业务领域模型。
2. 测试类
本教程的测试用例围绕 Person
类展开:
public class Person {
private String fullName;
private int age;
private List<String> nicknames;
public Person(String fullName, int age) {
this.fullName = fullName;
this.age = age;
this.nicknames = new ArrayList<>();
}
public void addNickname(String nickname) {
nicknames.add(nickname);
}
// getters
}
3. 自定义断言类
编写自定义 AssertJ 断言类非常简单。只需声明一个继承 AbstractAssert
的类,添加必需的构造函数,并实现自定义断言方法。
断言类必须继承 AbstractAssert
才能访问核心 API 的基础断言方法(如 isNotNull
和 isEqualTo
)。
以下是 Person
类的自定义断言类骨架:
public class PersonAssert extends AbstractAssert<PersonAssert, Person> {
public PersonAssert(Person actual) {
super(actual, PersonAssert.class);
}
// 后续描述的断言方法
}
继承 AbstractAssert
时需指定两个类型参数:
- 自定义断言类本身(用于方法链式调用)
- 被测试的类
为提供入口点,可定义静态方法启动断言链:
public static PersonAssert assertThat(Person actual) {
return new PersonAssert(actual);
}
接下来介绍 PersonAssert
类中的几个自定义断言方法:
✅ 全名验证:检查 Person
的全名是否匹配指定字符串:
public PersonAssert hasFullName(String fullName) {
isNotNull();
if (!actual.getFullName().equals(fullName)) {
failWithMessage("Expected person to have full name %s but was %s",
fullName, actual.getFullName());
}
return this;
}
✅ 成年验证:根据年龄判断是否成年:
public PersonAssert isAdult() {
isNotNull();
if (actual.getAge() < 18) {
failWithMessage("Expected person to be adult");
}
return this;
}
✅ 昵称验证:检查是否存在指定昵称:
public PersonAssert hasNickName(String nickName) {
isNotNull();
if (!actual.getNickNames().contains(nickName)) {
failWithMessage("Expected person to have nickname %s",
nickName);
}
return this;
}
当存在多个自定义断言类时,建议将所有 assertThat
方法封装到统一入口类:
public class Assertions {
public static PersonAssert assertThat(Person actual) {
return new PersonAssert(actual);
}
// 其他断言类的静态工厂方法
}
这个 Assertions
类作为所有自定义断言的统一入口,同名方法通过参数类型区分。
4. 实战演示
以下测试用例展示自定义断言的使用。注意:assertThat
方法从自定义 Assertions
类导入,而非 AssertJ 核心 API。
全名验证示例:
@Test
public void whenPersonNameMatches_thenCorrect() {
Person person = new Person("John Doe", 20);
assertThat(person)
.hasFullName("John Doe");
}
成年验证(失败用例):
@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
Person person = new Person("Jane Roe", 16);
// 断言将失败
assertThat(person).isAdult();
}
昵称验证(失败用例):
@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
Person person = new Person("John Doe", 20);
person.addNickname("Nick");
// 断言将失败
assertThat(person)
.hasNickname("John");
}
5. 断言生成器
为领域模型创建自定义断言类能显著提升测试可读性。
但若项目类数量庞大,手动创建所有断言类会非常耗时。这时 AssertJ 的断言生成器就派上用场了。
Maven 配置
在 pom.xml
添加插件:
<plugin>
<groupId>org.assertj</groupId>
<artifactId>assertj-assertions-generator-maven-plugin</artifactId>
<version>2.1.0</version>
<configuration>
<classes>
<param>com.baeldung.testing.assertj.custom.Person</param>
</classes>
</configuration>
</plugin>
插件最新版本查看这里
<classes>
元素指定需要生成断言的类。更多配置参考官方文档。
生成规则
AssertJ 生成器会为目标类的每个公共属性创建断言,方法名根据字段/属性类型自动生成。完整说明见参考手册。
使用步骤
- 在项目根目录执行:
mvn assertj:generate-assertions
- 生成的断言类位于
target/generated-test-sources/assertj-assertions
目录
生成的入口类示例:
// 生成注释已省略
package com.baeldung.testing.assertj.custom;
@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {
@org.assertj.core.util.CheckReturnValue
public static com.baeldung.testing.assertj.custom.PersonAssert
assertThat(com.baeldung.testing.assertj.custom.Person actual) {
return new com.baeldung.testing.assertj.custom.PersonAssert(actual);
}
protected Assertions() {
// empty
}
}
⚠️ 重要提醒:
- 将生成的源文件复制到测试目录
- 添加自定义断言方法满足特殊需求
- 生成器仍在完善中,代码可能不完全正确
- 建议作为辅助工具使用,而非完全依赖
6. 总结
本教程展示了如何手动和自动创建 AssertJ 自定义断言,提升测试代码可读性。
- 少量类:手动创建足够
- 大量类:推荐使用生成器
所有示例代码可在 GitHub 获取。