Reputation: 6285
I'm trying to use Hamcrest, but constantly run into the following:
Hamcrest matchers are shortcircuited, so for eg if I write:
Assert.assertThat(list, everyItem(not(isIn(shouldNotBeInList))));
Just the first faulty element of shouldNotBeInList is reported. I expect tests to tell me as much, as possible.
Could I write assertions in hamcrest, that they report nicely, so that all mismatches are reported, or should I create my own matchers or use another library?
Example output for
List<String> list = Arrays.asList("a", "b", "c");
List<String> shouldNotBeInList = Arrays.asList("c", "e", "a");
Notice no error message for c
Expected: every item is not one of {"c", "e", "a"}
but: an item was "a"
Upvotes: 2
Views: 375
Reputation: 10501
Hamcrest is a bit tricky when it comes to readable error messages. Some matchers create a helpful message with all errors, others (the most) report only the first error.
Of course you could create your own matcher with a "better" implementation and a good error message. Doing this for one or two matchers is okay, but this could end in reimplementing Hamcrest.
If using another library is an option for you, take a look at AssertJ. The assertion
Assertions.assertThat(list).doesNotContainAnyElementsOf(shouldNotBeInList);
gives this error message:
Expecting
<["a", "b", "c"]>
not to contain
<["c", "e", "a"]>
but found
<["c", "a"]>
Upvotes: 3
Reputation: 1114
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
List<String> shouldNotBeInList = Arrays.asList("c", "e", "a");
Assert.assertThat(list, everyFullCheck(not(isIn(shouldNotBeInList))));
}
public static class EveryFullCheck<T> extends TypeSafeDiagnosingMatcher<Iterable<T>> {
private final Matcher<? super T> matcher;
public EveryFullCheck(Matcher<? super T> matcher) {
this.matcher= matcher;
}
@Override
public boolean matchesSafely(Iterable<T> collection, Description mismatchDescription) {
boolean matches = true;
for (T t : collection) {
if (!matcher.matches(t)) {
if (!matches) {
mismatchDescription.appendText(", ");
}
mismatchDescription.appendText("an item ");
matcher.describeMismatch(t, mismatchDescription);
matches = false;
}
}
return matches;
}
@Override
public void describeTo(Description description) {
description.appendText("every item is ").appendDescriptionOf(matcher);
}
}
private static <U> EveryFullCheck<U> everyFullCheck(Matcher<? super U> matcher) {
return new EveryFullCheck<>(matcher);
}
}
Expected: every item is not one of {"c", "e", "a"} but: an item was "a", an item was "c"
Upvotes: 0