
AssertJ 默认的 withStrictTypeChecking() 会对整个对象图(包括集合容器类型)进行严格类型校验,但可通过自定义 RecursiveComparator 配置实现“仅对元素类型严格、忽略集合容器类型”的精准比对。
assertj 默认的 `withstricttypechecking()` 会对整个对象图(包括集合容器类型)进行严格类型校验,但可通过自定义 `recursivecomparator` 配置实现“仅对元素类型严格、忽略集合容器类型”的精准比对。
在使用 AssertJ 进行深度对象比较时,usingRecursiveComparison() 是处理嵌套结构的利器。但其 withStrictTypeChecking() 方法默认会对整个比较路径上的所有类型(含集合容器本身,如 SingletonList vs ArrayList)执行严格匹配,这往往不符合实际测试需求——我们通常只关心业务数据(如 TestClassA/TestClassB)的类型一致性,而非底层集合实现类是否完全相同。
幸运的是,AssertJ 提供了更底层的控制入口:RecursiveComparator 配合 RecursiveComparisonConfiguration。该方案允许你精细调控类型检查粒度,实现「容器类型宽松、元素类型严格」的行为。
以下为 Kotlin 示例(Java 同理):
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.recursive.comparison.RecursiveComparator
import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration
@Test
fun `test strict type checking only on elements`() {
val listOfA = listOf(TestClassA("Name"))
val arrayListOfA = arrayListOf(TestClassA("Name"))
val arrayListOfB = arrayListOf(TestClassB("Name"))
// ✅ 容器类型不同(SingletonList vs ArrayList)但元素类型一致 → 通过
val configForLooseContainer = RecursiveComparisonConfiguration().apply {
strictTypeChecking(false) // 关键:禁用全局严格类型检查
}
assertThat(listOfA)
.usingElementComparator(RecursiveComparator(configForLooseContainer))
.isEqualTo(arrayListOfA)
// ❌ 元素类型不同(TestClassA vs TestClassB)→ 失败(符合预期)
assertThat(listOfA)
.usingElementComparator(RecursiveComparator(configForLooseContainer))
.isEqualTo(arrayListOfB) // AssertionError: expected:<[TestClassB(name=Name)]> but was:<[TestClassA(name=Name)]>
// ✅ 启用元素级严格类型检查(仍忽略容器类型)
val configForStrictElements = RecursiveComparisonConfiguration().apply {
strictTypeChecking(true) // 仅对非容器节点(如元素对象)启用类型校验
}
assertThat(listOfA)
.usingElementComparator(RecursiveComparator(configForStrictElements))
.isEqualTo(arrayListOfA) // 通过:元素同为 TestClassA
// ❌ 元素类型不匹配 → 明确失败
assertThat(listOfA)
.usingElementComparator(RecursiveComparator(configForStrictElements))
.isNotEqualTo(arrayListOfB) // 通过:正确识别 TestClassA ≠ TestClassB
}关键要点说明:
-
strictTypeChecking(true)并非“全量严格”,而是作用于递归遍历中每个字段值的运行时类型;对于集合本身,AssertJ 在比较其内容时会跳过容器类型校验,聚焦于元素实例类型。 - 必须搭配
.usingElementComparator(...)使用(而非.usingRecursiveComparison()),因为后者封装了更高层逻辑,无法绕过容器类型检查。 - 此方式保留了
RecursiveComparator的全部能力(如字段过滤、自定义比较器等),适合复杂领域模型的精准断言。
⚠️ 注意:该方案虽略失“流式 API”的简洁性,却是目前 AssertJ(v3.24+)中唯一能解耦容器与元素类型校验粒度的官方支持方式。避免使用反射或手动遍历,确保测试稳定性和可维护性。

















