AssertJ的核心优势是链式调用与高可读性,支持分层断言、精准提取、软断言、自定义断言及异常/异步精细验证。

用好 assertThat 的链式断言
AssertJ 的核心优势在于链式调用,它让断言像自然语言一样可读。关键不是堆砌方法,而是按验证逻辑分层组织。
- 先校验存在性或基础状态(如 isNotNull()、isNotEmpty()),再深入内容检查
- 字符串验证推荐组合使用:isNotBlank().startsWith("API").contains("success").endsWith("v2")
- 数字比较优先用语义化方法:isGreaterThan(0).isLessThanOrEqualTo(100),比 isEqualTo(42) 更具业务含义
- 避免无意义链式:不要写 isEqualTo(x).isEqualTo(x),单次断言足够时不必强行链
精准提取与结构化断言集合
面对 List
- 用 extracting("name", "age") 或 extracting(User::getName, User::getAge) 拿出字段值列表,再做 containsExactly("Alice", 25)
- 嵌套对象可用 extracting("address.city"),支持点号路径,无需手动遍历
- 验证 Map 时,用 containsEntry("status", "ACTIVE") 或 hasSize(3),比转成 entrySet 再 assert 清晰得多
- 对 JSON 响应体,先用工具类转为 Map 或 JsonNode,再用 extractingJsonPathStringValue("$.data.id")(需搭配 assertj-json)
软断言:一次执行多个独立校验
当一个测试需同时验证多个不相互依赖的条件(比如返回对象的 ID、时间戳、状态码都得对),传统硬断言会因第一个失败而中断。软断言解决这个问题。
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
- 引入 SoftAssertions:用 new SoftAssertions() 实例替代静态 assertThat
- 所有断言调用其方法,如 softly.assertThat(user.getId()).isPositive()、softly.assertThat(user.getCreatedAt()).isBeforeNow()
- 最后必须调用 softly.assertAll() —— 它会汇总全部失败项,一次性报错
- 适合 DTO 全字段校验、API 响应多维度断言等场景,不适用于有前置依赖的断言链
自定义断言提升业务语义
通用断言无法表达领域规则,比如“订单金额不能为负且必须保留两位小数”。这时可封装专用断言类。
- 继承 AbstractAssert
,实现构造函数和校验方法:hasValidAmount()、isPaid() - 在测试中直接写:assertThat(order).hasValidAmount().isPaid(),语义一目了然
- 复用性强:同一套断言可在多个测试类中使用,且错误信息自动带上下文(如 “Expected order amount to be positive and rounded to 2 decimals”)
- 配合静态导入:import static com.example.test.assertions.OrderAssert.assertThat;,彻底隐藏底层实现
异常与异步操作的可靠断言
AssertJ 对异常和延迟行为的支持比原生 JUnit 更精细,尤其适合 Spring WebFlux、CompletableFuture 场景。
- 捕获并断言异常细节:assertThatThrownBy(() -> service.process(null)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("user id cannot be null")
- 验证 CompletableFuture:assertThatCode(() -> service.asyncCall().join()) .doesNotThrowAnyException(),或配合 await().untilAsserted()(需 assertj-concurrent)
- 超时控制更明确:不用自己写 while + Thread.sleep,用 await().atMost(3, SECONDS).until(() -> condition())
- 注意:assertThatThrownBy 返回的是 ThrowableAssert,后续方法链针对异常本身,不是原始方法的返回值
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










