Hamcrest的hasItems,contains和containsInAnyOrder有何不同?

Joe*_*Joe 50 hamcrest

Hamcrest提供了许多用于断言集合内容的匹配器.所有这些案件都通过:

Collection<String> c = ImmutableList.of("one", "two", "three");
assertThat(c, hasItems("one", "two", "three");
assertThat(c, contains("one", "two", "three");
assertThat(c, containsInAnyOrder("one", "two", "three");
Run Code Online (Sandbox Code Playgroud)

如何hasItems,contains以及containsInAnyOrder有什么不同?

Joe*_*Joe 65

hasItems检查:

连续遍历检查的Iterable yield至少一个项目,该项目等于指定的相应项目items.

也就是说,它确保集合包含任何顺序的至少这些项目.所以,

assertThat(c, hasItems("one", "two"));
Run Code Online (Sandbox Code Playgroud)

也会通过,额外的项目被忽略.和:

assertThat(c, hasItems("three", "two", "one"));
Run Code Online (Sandbox Code Playgroud)

也会通过.

contains检查:

对检查的单次传递Iterable产生一系列项目,每个项目在逻辑上等于指定项目中的相应项目.对于肯定匹配,检查的iterable必须与指定项的数量具有相同的长度.

因此,它可以确保集合包含正是这些项目:

assertThat(c, contains("one", "two")); // Fails
Run Code Online (Sandbox Code Playgroud)

这将失败,因为剩余"three"的不匹配.

assertThat(c, contains("three", "two", "one")); // Fails
Run Code Online (Sandbox Code Playgroud)

这会失败,因为相应的项目不匹配.

另一个相关的匹配,containsInAnyOrder,检查恰好这些项目都存在,但在任何顺序:

Iterables当一次检查Iterable产生一系列项目时,为该匹配创建一个与订单无关的匹配器,每个项目在逻辑上等于指定项目中任何位置的一个项目.

缺少项目的测试失败:

assertThat(c, containsInAnyOrder("one", "two")); // Fails
Run Code Online (Sandbox Code Playgroud)

但是,不同顺序的所有项目都将通过:

assertThat(c, containsInAnyOrder("three", "two", "one"));
Run Code Online (Sandbox Code Playgroud)

  • `contains`是一个大错的用词.我原以为`contains`和`Collection#contains`一样. (10认同)
  • [AssertJ](https://joel-costigliola.github.io/assertj/) 调用这个方法 [`containsExactly`](https://joel-costigliola.github.io/assertj/core/api/org/assertj/ core/api/ObjectEnumerableAssert.html#containsExactly%28ELEMENT...%29),这也可能有助于减少意外。 (4认同)
  • 我会将contains重命名为includesOf (3认同)
  • 如果我想使用 containsInAnyOrder,但列表包含重复项怎么办?例如,我想检查 List 是否包含确切的元素,但它们有重复项 - 在这种情况下 containsAnyOrder("三","三","一") 将成立,即使测试的列表只有 ("三,"一") 元素。如何处理这个问题? (3认同)