50

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

6 回答 6

62

您可以改用containsmatcher,但您可能需要使用最新版本的 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);
  }
于 2013-03-25T06:58:07.110 回答
9

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

来自 javadoc:

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

实际适用于 Java Hamcrest 2.0.0.0。

希望这可以帮助。

于 2015-06-18T12:14:56.900 回答
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"));
}
于 2013-03-25T07:00:08.890 回答
1

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

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

所以我写了自己的 IsIterableContainingInRelativeOrder,并以 patch 的形式提交

于 2014-04-23T19:16:47.750 回答
1

我在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)

于 2015-01-12T17:56:35.297 回答
0

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

使用示例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 处的不匹配并进行最终修复。

于 2019-10-30T19:13:55.470 回答