AssertJ使用assertThatThrownBy方法时如何获取实际异常实例
AssertJ 提取自定义异常实例的实现方案
从JUnit 5、Hamcrest迁移到AssertJ时,不需要手动捕获Throwable再强转,AssertJ本身提供了类型安全的API可以实现同等校验效果,常用写法有三种:
- 链式断言(最推荐)
不需要额外持有异常实例变量,直接用assertThatExceptionOfType指定预期异常类型,所有校验逻辑链式写完即可:
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; assertThatExceptionOfType(MyException.class) .isThrownBy(() -> this.objectUnderTest.someMethod(param1, param2, param3)) .extracting("error.errorCode", "error.description") .containsExactly(someValue, "someString");
如果有复杂的自定义校验规则,可以在链式调用中加matches方法传入校验谓词。
- 提取指定类型异常实例(适合需要复用异常对象的场景)
如果后续逻辑需要反复调用自定义异常的方法、或者要做复杂的多步校验,用catchThrowableOfType方法,它会直接返回你指定类型的异常对象,不需要手动强转,同时自带类型校验:如果实际抛出的异常不是目标类型,会直接抛出断言失败,比手动强转类型更安全。
import static org.assertj.core.api.Assertions.catchThrowableOfType; MyException exception = catchThrowableOfType( () -> this.objectUnderTest.doFilterInternal(param1, param2, param3), MyException.class ); assertThat(exception.getError().getErrorCode()).isEqualTo(someValue); assertThat(exception.getError().getDescription()).isEqualTo("someString");
- 沿用
assertThatThrownBy写法做流式校验
如果你习惯用assertThatThrownBy的入口,不需要提取异常实例也可以直接完成内部属性校验:
import static org.assertj.core.api.Assertions.assertThatThrownBy; assertThatThrownBy(() -> this.objectUnderTest.someMethod(param1, param2, param3)) .isInstanceOf(MyException.class) .extracting( e -> ((MyException) e).getError().getErrorCode(), e -> ((MyException) e).getError().getDescription() ) .containsExactly(someValue, "someString");
注意:
assertThatThrownBy的定位是通用异常流式断言入口,没有暴露获取具体类型异常实例的公开方法,不要通过反射或者读取内部私有字段的方式从它的返回值里取原始异常,否则代码会和AssertJ具体版本强绑定,后续升级依赖很容易失效。
内容的提问来源于stack exchange,提问作者Arthur Eirich
相关产品推荐
相关产品推荐

