How to check if collection contains items in given order using Hamcrest
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
)
Mariusz Jamro
Updated on October 31, 2020Comments
-
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 about 11 years+1 Yes, update to the latest JUnit and Hamcrest, though
contains
has been around for a while. -
Kevin Pauli about 10 yearsWhat version of Hamcrest? For me, 1.3 is causing: java.lang.AssertionError: Expected: iterable containing ["foo", "boo"] but: Not matched: "bar"
-
Marek over 9 yearsOMG. 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 over 9 yearsWelcome to Stack Overflow. Here, it is better to include important parts of code in your answer.
-
vvursT about 9 yearsthe 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 about 6 yearsActually, 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?