I'm using Java8 and am trying to write a test helper that will validate the exception thrown is of a specific type. Here's an initial version that works:
private static <E extends Exception> void expectThrow(Callable<Void> callable, Class<E> exceptionClass) {
try {
callable.call();
} catch (Exception e) {
assertTrue(exceptionClass.isInstance(e));
}
}
What I'd like to do is replace the catch block with a hamcrest matcher so I get more useful info from failures:
assertThat(e, Matchers.isA(exceptionClass));
but this doesn't compile - I get this lovely error: The method assertThat(T, Matcher<? super T>) in the type Assert is not applicable for the arguments (Exception, Matcher<E>)
This puzzles me - shouldn't this work? This seems similar to the following case, which works perfectly fine:
Integer a = 3;
assertThat(a, Matchers.isA(Number.class));
After playing around somewhat, the following also works:
assertThat((E)e, Matchers.isA(exceptionClass));
Though that gives me a helpful "unchecked cast from Exception to E" type safety warning. I know I can't catch (E e)
- type erasure and all...
What's going on? How can I update my test helper in a nice typesafe way?
This seems to be a long-standing issue finally fixed 5 days ago. The signature for isA
was broken. Until the next release of Hamcrest makes the fix available, and until your project is using that release, you'll have to use
assertThat(e, is(instanceOf(exceptionClass)))