Warm tip: This article is reproduced from stackoverflow.com, please click
java assertj

Matching custom exceptions

发布于 2020-03-29 21:01:44

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?

Questioner
DodgyCodeException
Viewed
16
Joel Costigliola 2020-02-01 10:29

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.