Search code examples
javaassertj

Matching custom exceptions


The Javadoc gives this example for the matches method:

assertThat(player).matches(p -> p.isRookie());

And indeed, when I define a dummy class Player, the above statement compiles ok. However, when I define a class that derives from Exception, then the following doesn't compile:

public class MyCustomException extends Exception {
    public boolean isMyCustomFieldSet() { return true; }
}
...
MyCustomException myCustomException = new MyCustomExcpetion();
assertThat(myCustomException).matches(e -> e.isMyCustomFieldSet());

I can make it compile by using a cast:

assertThat(myCustomException).matches(e -> ((MyCustomException)e).isMyCustomFieldSet());

but that cast looks "ugly" and a bit of a hack to work around some sort of deficiency. Can I make it compile in a "nicer" way, i.e. without using a cast?


Solution

  • The issue is in Assertions, it declares AbstractThrowableAssert<?, ? extends Throwable> assertThat(Throwable t) instead of <T> AbstractThrowableAssert<?, T extends Throwable> assertThat(T t)

    But unfortunately this can not be done because of the following existing method that clashes with it: public static <T> ObjectAssert<T> assertThat(T actual).

    Casting is a solution, I agree it is not super elegant.

    What I would do in that case is simply:

    assertThat(myCustomException.isMyCustomFieldSet()).isTrue();
    

    or to keep assertions on myCustomException directly:

    assertThat(myCustomException).hasFieldOrPropertyWithValue("myCustomFieldSet", true)
                                 .hasFieldOrPropertyWithValue("myOtherField", "foo");
    
    

    The drawback here is accessing fields by name which is not refactoring friendly.