如何用AssertJ测试不同类型列表的转换正确性?
AssertJ 列表转换测试:替代循环的索引对应断言方案
问题场景
我实现了一个列表转换器,方法签名如下:
List<Bar> convert(List<Foo> input)
想用AssertJ编写测试用例,已经实现了单个Foo到Bar的转换验证方法assertThatConvertedCorrectly(Foo foo, Bar bar)。现有测试框架代码:
@Test void test() { List<Foo> input = generateInput(); List<Bar> actual = converter.convert(input); // TODO 断言输入列表被正确转换为输出列表 }
目前通过for循环完成断言,但希望用更简洁、类似containsExactlyElementsOf的自定义断言逻辑替代以下代码:
assertThat(actual).hasSameSize(input); for(int i = 0; i < actual.size(); i++) { Foo foo = input.get(i); Bar bar = actual.get(i); assertThatConvertedCorrectly(foo, bar); }
需求是验证实际输出列表的每个元素与输入列表对应索引的元素完成了正确转换。
解决方案
1. 推荐:使用zipSatisfying(AssertJ 3.21及以上版本)
AssertJ 3.21新增的zipSatisfying方法专门用于配对两个列表的对应元素,自动验证列表大小一致,然后逐个执行自定义断言逻辑,完全替代循环:
assertThat(actual).zipSatisfying(input, (bar, foo) -> { assertThatConvertedCorrectly(foo, bar); });
2. 旧版本兼容:indexed() + allSatisfy
如果你的AssertJ版本低于3.21,可以先验证列表大小一致,再通过indexed()获取元素索引,关联输入列表的对应元素进行断言:
assertThat(actual) .hasSameSizeAs(input) .allSatisfy((bar, index) -> { Foo foo = input.get(index); assertThatConvertedCorrectly(foo, bar); });
3. 预生成预期列表的场景
如果可以预先从输入列表生成预期的Bar列表,也可以用自定义比较器结合containsExactlyElementsOf:
// 先从输入生成预期的Bar列表 List<Bar> expected = input.stream() .map(this::convertSingleFooToBar) // 单个Foo转Bar的逻辑 .collect(Collectors.toList()); // 自定义比较器,复用转换验证方法 Comparator<Bar> conversionComparator = (actualBar, expectedBar) -> { // 执行转换正确性断言,失败会直接抛出AssertionError assertThatConvertedCorrectly(/* 若需依赖原Foo则不适合此方式,更适合直接比较Bar对象 */); return 0; }; assertThat(actual) .usingElementComparator(conversionComparator) .containsExactlyElementsOf(expected);
注意:这种方式更适合直接比较Bar对象的场景,如果必须依赖原Foo进行验证,前两种方法更合适。
内容的提问来源于stack exchange,提问作者mohammad
相关产品推荐
相关产品推荐

