【问题标题】:How to check if collection contains items in given order using Hamcrest如何使用 Hamcrest 检查集合是否包含给定顺序的项目
【发布时间】:2013-03-25 06:44:26
【问题描述】:

如果给定的集合包含给定顺序的给定项目,如何使用 Hamcrest 检查?我试过hasItems,但它只是忽略了订单。

List<String> list = Arrays.asList("foo", "bar", "boo");

assertThat(list, hasItems("foo", "boo"));

//I want this to fail, because the order is different than in "list"
assertThat(list, hasItems("boo", "foo")); 

【问题讨论】:

  • 考虑更改接受的答案。通常,当我们搜索匹配器时,我们会优先考虑那些已经在 API 中的匹配器,而将自定义匹配器留给不可避免的情况。
  • 接受的答案不回答问题。该问题要求匹配器仅检查预期项目是否按给定顺序包含在实际列表中,而不是所有实际项目。 Matchers.contains 方法检查列表是否包含预期的项目。
  • 在这个问题中解释了其他匹配器stackoverflow.com/a/44030511/1195507

标签: java collections hamcrest


【解决方案1】:

您可以改用contains matcher,但您可能需要使用最新版本的 Hamcrest。该方法检查订单。

assertThat(list, contains("foo", "boo"));

如果顺序对您不重要,您也可以尝试使用containsInAnyOrder

这是contains匹配器的代码:

  public static <E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers)
  {
    return IsIterableContainingInOrder.contains(itemMatchers);
  }

【讨论】:

  • +1 是的,更新到最新的 JUnit 和 Hamcrest,尽管 contains 已经存在了一段时间。
  • 什么版本的 Hamcrest?对我来说,1.3 导致:java.lang.AssertionError: Expected: iterable contains ["foo", "boo"] but: Not match: "bar"
  • 该解决方案不适用于结果列表的给定子集,因为 contains-Matcher 失败,出现预期项目数组中未给出的任何额外项目。
【解决方案2】:

要检查集合是否包含预期(给定)顺序的项目,您可以使用 Hamcrest 的 containsInRelativeOrder 方法。

来自 javadoc:

为 Iterable 创建一个匹配器,当单次通过时匹配 检查的 Iterable 产生一系列项目,其中包含项目 逻辑上等于指定项中的对应项,在 相同的相对顺序 例如:assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d"))。

Java Hamcrest 2.0.0.0 的实际值。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    你需要实现一个自定义的 Matcher,像这样

    class ListMatcher extends BaseMatcher {
        String[] items;
    
        ListMatcher(String... items) {
            this.items = items;
        }
    
        @Override
        public boolean matches(Object item) {
            List list = (List) (item);
            int l = -1;
            for (String s : items) {
                int i = list.indexOf(s);
                if (i == -1 || i < l) {
                    return false;
                }
                l = i;
            }
            return true;
        }
    
        @Override
        public void describeTo(Description description) {
            // not implemented
        }
    }
    
    @Test
    public void test1() {
        List<String> list = Arrays.asList("foo", "bar", "boo");
        Assert.assertThat(list, new ListMatcher("foo", "boo"));
        Assert.assertThat(list, new ListMatcher("boo", "foo"));
    }
    

    【讨论】:

    • 天啊。这个匹配器是丑陋的和错误的。它应该扩展 TypeSafeMatcher。或者至少检查 match() 方法中的项目实例 - 目前您可以获得 ClassCastExecption。它应该是一个泛型类型,因为目前它只适用于字符串。它应该处理空值。 match() 的复杂度为 O(n^2)。还有...
    【解决方案4】:

    接受的答案对我不起作用。它仍然失败,说

    Expected: iterable containing ["foo", "boo"] but: Not matched: "bar"
    

    所以我编写了自己的 IsIterableContainingInRelativeOrder 和 submitted it as a patch

    【讨论】:

    • 实际上,您应该将断言更改为也查找“bar”。这是您的单元测试,您当然应该知道 SUT 的结果包括列表中的元素“bar”?
    【解决方案5】:

    我在http://www.baeldung.com/hamcrest-collections-arrays找到了解决方案

    查找具有严格顺序示例的部分。

    List<String> collection = Lists.newArrayList("ab", "cd", "ef");
    assertThat(collection, contains("ab", "cd", "ef"));
    

    基本上你需要使用 contains Matcher (org.hamcrest.Matchers.contains)

    【讨论】:

    • 欢迎来到 Stack Overflow。在这里,最好在答案中包含重要的代码部分。
    【解决方案6】:

    您可以组合匹配器库的isequalTo。 assert 语句看起来更长,但错误消息更好。因为contains 是先失败,所以它会在发现第一个不匹配时中断,并且不会在列表的下方找到失败。其中isequalTo 将打印整个列表,您可以从中看到所有不匹配。

    使用contains的示例

    List<String> list = Arrays.asList("foo", "bar", "boo");
    assertThat(list, contains("foo", "boo", "bar"));
    

    给出以下错误信息:

    Expected: iterable containing ["foo", "boo", "bar"]
     but: item 1: was "bar"
    

    使用is and equalTo的示例

    List<String> list = Arrays.asList("foo", "bar", "boo");
    assertThat(list, is(equalTo(Lists.newArrayList("foo", "boo", "bar"))));
    

    给出以下错误信息:

    Expected: is <[foo, boo, bar]>
         but: was <[foo, bar, boo]>
    

    第二种方法不会告诉您不匹配的索引,但对我来说这仍然更好,因为您只需查看一次失败消息即可修复测试。而在方法一中,您将首先修复索引 1,运行测试,检测索引 2 处的不匹配并进行最终修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-16
      • 2019-01-28
      • 2021-07-02
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 2017-06-04
      相关资源
      最近更新 更多