I have a custom exception class:
```java
public class SomeException extends RuntimeException {
private final Set<Integer> something;
public SomeException(String message, Set<Integer> something) {
super(message);
this.something = something;
}
public Set<Integer> getSomething() {
return something;
}
}
In my test, I want to verify both the exception type and that the something field contains specific values:
assertThatThrownBy(() -> service.doSomething())
.isInstanceOf(SomeException.class)
.hasMessageStartingWith("SomeException has 1,2,3,4 in something field")
// how to assert that SomeException.getSomething() contains 1,2,3,4?
Using extracting() directly doesn’t work because AssertJ treats it as a Throwable. I’ve tried:
SomeException throwable = (SomeException) catchThrowable(() -> service.doSomething());
assertThat(throwable)
.hasMessageStartingWith("Works except containsExactlyInAnyOrder()")
.asInstanceOf(InstanceOfAssertFactories.type(SomeException.class))
.extracting(SomeException::getSomething)
// want to assert containsExactlyInAnyOrder here
But `containsExactlyInAnyOrder()` is not working as expected. How can I properly assert the `something` field using `assertThatThrownBy()`?
Since assertThatThrownBy returns a ThrowableAssert, you can use satisfies to inspect the exception and assert fields:
assertThatThrownBy(() -> service.doSomething())
.isInstanceOf(SomeException.class)
.hasMessageStartingWith("SomeException has 1,2,3,4 in something field")
.satisfies(throwable -> {
SomeException ex = (SomeException) throwable;
assertThat(ex.getSomething()).containsExactlyInAnyOrder(1, 2, 3, 4);
});
I use this pattern whenever I need to check additional fields in a custom exception—it keeps everything in one fluent assertion.
AssertJ allows type-safe assertions on custom exceptions via asInstanceOf:
assertThatThrownBy(() -> service.doSomething())
.isInstanceOf(SomeException.class)
.asInstanceOf(InstanceOfAssertFactories.type(SomeException.class))
.satisfies(ex -> assertThat(ex.getSomething()).containsExactlyInAnyOrder(1, 2, 3, 4));
This avoids manual casting and integrates nicely with other AssertJ fluent assertions. I often prefer this style for readability and type safety.
Alternatively, you can catch the exception first and then assert on its fields:
SomeException ex = (SomeException) catchThrowableOfType(() -> service.doSomething(), SomeException.class);
assertThat(ex.getSomething()).containsExactlyInAnyOrder(1, 2, 3, 4);
assertThat(ex).hasMessageStartingWith("SomeException has 1,2,3,4 in something field");
This is useful when you want to split exception type/message checks from field assertions, or if you find assertThatThrownBy with satisfies too verbose.