How to check if collection contains items in given order using Hamcrest

61,016

Solution 1

You can use contains matcher instead, but you probably need to use latest version of Hamcrest. That method checks the order.

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

You can also try using containsInAnyOrder if order does not matter to you.

That's the code for contains matcher:

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

Solution 2

To check tha collection contains items in expected (given) order you can use Hamcrest's containsInRelativeOrder method.

From javadoc:

Creates a matcher for Iterable's that matches when a single pass over the examined Iterable yields a series of items, that contains items logically equal to the corresponding item in the specified items, in the same relative order For example: assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d")).

Actual for Java Hamcrest 2.0.0.0.

Hope this helps.

Solution 3

You need to implement a custom Matcher, something like this

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

Solution 4

The accepted answer is not working for me. It still fails, saying

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

So I wrote my own IsIterableContainingInRelativeOrder, and submitted it as a patch.

Solution 5

I found a solution at http://www.baeldung.com/hamcrest-collections-arrays

Look for the section that has an example with strict order.

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

Basically you need to use the contains Matcher (org.hamcrest.Matchers.contains)

Share:
61,016
Mariusz Jamro
Author by

Mariusz Jamro

Updated on October 31, 2020

Comments

  • Mariusz Jamro
    Mariusz Jamro over 3 years

    How to check using Hamcrest if given collection is containing given items in given order? I tried hasItems but it simply ignores the order.

    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")); 
    
  • David Harkness
    David Harkness about 11 years
    +1 Yes, update to the latest JUnit and Hamcrest, though contains has been around for a while.
  • Kevin Pauli
    Kevin Pauli about 10 years
    What version of Hamcrest? For me, 1.3 is causing: java.lang.AssertionError: Expected: iterable containing ["foo", "boo"] but: Not matched: "bar"
  • Marek
    Marek over 9 years
    OMG. This matcher is ugly and buggy. It should extend TypeSafeMatcher. Or least check instance of item in the matches() methods - currently you can get ClassCastExecption. And it should be a generic type, because currently it works for Strings only. And it should handle null. And the matches() has O(n^2) complexity. And ...
  • AliLotfi
    AliLotfi over 9 years
    Welcome to Stack Overflow. Here, it is better to include important parts of code in your answer.
  • vvursT
    vvursT about 9 years
    the solution won't work for a given subset of the result list, because contains-Matcher fails with any extra item not given in the expected item array.
  • Frans
    Frans about 6 years
    Actually, you should change your assertion to also look for "bar". It's your unit test, surely you should know that the outcome of your SUT includes the element "bar" being in the list?