Reputation: 5318
While testing a Set
with JUnit and Hamcrest Matchers I've noticed that Matchers.contains()
method gives a pretty good clue on what's wrong with the test. On the other hand Matchers.containsInAnyOrder()
difference report is almost useless. Here's the test code:
Simple bean:
public class MyBean {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
JUnit test:
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyTest {
@Test
public void hamcrestTest() {
Set<MyBean> beanSet = new HashSet<MyBean>();
MyBean bean = new MyBean();
bean.setId(1);
beanSet.add(bean);
bean = new MyBean();
bean.setId(2);
beanSet.add(bean);
assertThat(beanSet, contains(
hasProperty("id", is(1)),
hasProperty("id", is(3))
));
}
}
As you could see actual bean id's are 1
and 2
while expected ones are 1
and 3
so the test fails.
Test result:
java.lang.AssertionError:
Expected: iterable over [hasProperty("id", is <1>), hasProperty("id", is <3>)] in any order
but: Not matched: <MyBean@4888884e
If I switch to Matchers.contains()
method then the result is much more informative:
java.lang.AssertionError:
Expected: iterable containing [hasProperty("id", is <1>), hasProperty("id", is <3>)]
but: item 0: property 'id' was <2>
Unfortunately, since a Set is not ordered contains()
is not an option in this case.
Finally the question:
Is it somehow possible to get a better error report when asserting a Set
with hamcrest?
Upvotes: 5
Views: 10557
Reputation: 13696
Hamcrest seems to have different implementations for how mismatches are reported for the contains
and the containsInAnyOrder
matchers.
The containsInAnyOrder
just gives you the item's toString()
value by doing this:
mismatchDescription.appendText("Not matched: ").appendValue(item);
While the contains
matcher does a better job by delegating to the actual matcher's describeMismatch()
:
matcher.describeMismatch(item, mismatchDescription);
Hence you see the hasProperty
matcher's additional information in this case but not while using containsInAnyOrder
.
I think the best you can do in this case is to implement a toString()
for your MyBean
class.
There is already an issue reported about this: https://github.com/hamcrest/JavaHamcrest/issues/47
Upvotes: 2