Question
Assume the following simple test:
@Test
public void test() throws Exception {
Object value = 1;
assertThat(value, greaterThan(0));
}
The test won't compile, because "greaterThan" can only be applied to instances of type Comparable
. But I want to assert that value
is an Integer which is greater than zero. How can I express that using Hamcrest?
What I tried so far:
The simple solution would be to simply remove the generics by casting the matcher like that:
assertThat(value, (Matcher)greaterThan(0));
Possible, but generates a compiler warning and feels wrong.
A lengthy alternative is:
@Test
public void testName() throws Exception {
Object value = 1;
assertThat(value, instanceOfAnd(Integer.class, greaterThan(0)));
}
private static<T> Matcher<Object> instanceOfAnd(final Class<T> clazz, final Matcher<? extends T> submatcher) {
return new BaseMatcher<Object>() {
@Override
public boolean matches(final Object item) {
return clazz.isInstance(item) && submatcher.matches(clazz.cast(item));
}
@Override
public void describeTo(final Description description) {
description
.appendText("is instanceof ")
.appendValue(clazz)
.appendText(" and ")
.appendDescriptionOf(submatcher);
}
@Override
public void describeMismatch(final Object item, final Description description) {
if (clazz.isInstance(item)) {
submatcher.describeMismatch(item, description);
} else {
description
.appendText("instanceof ")
.appendValue(item == null ? null : item.getClass());
}
}
};
}
Feels "tidy" and "correct", but it is really a lot of code for something that seems simple. I attempted to find something like that built-in in hamcrest, but I was not successful, but maybe I missed something?
Background
In my actual test case the code is like this:
Map<String, Object> map = executeMethodUnderTest();
assertThat(map, hasEntry(equalTo("the number"), greaterThan(0)));
In my simplified case in the question I could also write assertThat((Integer)value, greaterThan(0))
. In my actual case I could write assertThat((Integer)map.get("the number"), greaterThan(0)));
, but that would of course worsen the error message if something is wrong.