使用assertj / Java比较具有列表字段的对象,忽略列表中元素的顺序

12

我想要比较2个对象列表(例如Foo)在测试中的不同。

List<Foo> fooA;
List<Foo> fooB;

每个Foo条目都有一个类型为List(比如说Bar)的字段。
class Foo {
  private List<Bar> bars;
  ....
}

assertThat(fooA).isEqualTo(fooB);

由于条形图中的元素相同但顺序不同,因此比较会失败。

有没有一种忽略顺序进行比较的方法?

我不想使用以下选项。

assertThat(fooA).usingElementComparatorIgnoringFields("bars").isEqualTo(fooB);

理想情况下,我希望能够比较所有的字段。


4
即使这两个列表项按照相同的顺序排列,比较也会失败,因为这两个列表是不同的对象。 - forpas
2
请查看此答案 - StaticBeagle
1
愚蠢的问题:Foo 是否定义了 equals 方法? - Makoto
Foo类已定义了一个equals方法,它检查两个列表字段是否相等。我尝试将其更新为检查containsAll,但没有帮助。 - Random
对于Groovy,请使用@EqualsAndHashCode。对于Java,请覆盖equals/hashcode方法。 - Gaurav
2个回答

11

你可以使用AssertJ完成此操作:

assertThat(fooA).usingRecursiveComparison().ignoringCollectionOrder().isEqualTo(fooB)

1
递归比较允许您逐个字段进行递归比较,即使它们不是相同类型的。 - IamDOM
这个答案在处理包含具有不同偏移量的OffsetDateTime的列表条目的containsExactlyInAnyOrderElementsOf问题时拯救了我的一天。可以通过.usingRecursiveComparison().ignoringCollectionOrder().withComparatorForType(Comparator.comparing(a -> a.withOffsetSameInstant(ZoneOffset.UTC)),OffsetDateTime.class).isEqualTo(List.of(...来解决这个问题。 - undefined

5
你要查找的是IterableAssert中定义的containsExactlyInAnyOrderElementsOf(Iterable)方法(其中强调的是我的):

验证实际集合恰好包含给定的值无序且不包含其他元素。

你可以这样写:
List<Foo> fooA;
List<Foo> fooB;
//...
assertThat(fooA).containsExactlyInAnyOrderElementsOf(fooB);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接