如何使用Hamcrest检查集合是否包含给定顺序的项目

时间:2013-03-25 06:44:26

标签: java collections hamcrest

如果给定的集合包含给定顺序的给定项目,如何使用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")); 

6 个答案:

答案 0 :(得分:49)

您可以使用contains匹配器,但您可能需要使用最新版本的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 :(得分:7)

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

来自javadoc:

  

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

Java Hamcrest 2.0.0.0的实际值。

希望这有帮助。

答案 2 :(得分:2)

您需要实现自定义匹配器,类似这样

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"));
}

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

我在http://www.baeldung.com/hamcrest-collections-arrays

找到了解决方案

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

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

基本上你需要使用包含匹配器(org.hamcrest.Matchers.contains

答案 5 :(得分:0)

您可以组合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的不匹配并进行最终修复。