Junit5扩展抛出的异常能否被其他扩展捕获?
结论
你的推测是正确的,LifecycleMethodExecutionExceptionHandler 仅能捕获测试类本身定义的生命周期方法抛出的异常,无法捕获扩展回调方法抛出的异常,不管是当前扩展自己的回调还是其他扩展的回调都不支持。
原理解释
JUnit 5 对 LifecycleMethodExecutionExceptionHandler 的设计定位就是处理测试类中被 @BeforeAll/@BeforeEach/@Test/@AfterEach/@AfterAll 注解标注的自定义方法的执行异常,而扩展本身实现的回调接口(比如 BeforeAllCallback、BeforeEachCallback 等)属于JUnit扩展框架的执行逻辑,不在该处理器的处理范围内。
你示例中抛出异常的位置是 ExceptionThrowingExtension 实现的 beforeAll 回调方法,不属于测试类的生命周期方法,因此不会触发任何 LifecycleMethodExecutionExceptionHandler 的执行,这就是你看不到对应日志的原因。
适配你的需求的解决方案
你的第二个扩展需要收集所有失败测试的唯一标识,包括扩展抛异常导致的测试失败场景,不需要用 LifecycleMethodExecutionExceptionHandler,改为实现 TestWatcher 接口即可:
class TestFailCollectExtension: TestWatcher { @Throws(Throwable::class) override fun testAborted(context: ExtensionContext, cause: Throwable) { // 扩展抛异常、测试被跳过等中止场景会进入该方法 println("测试中止,唯一标识:${context.uniqueId},异常原因:${cause.message}") // 此处添加存储标识的逻辑 } @Throws(Throwable::class) override fun testFailed(context: ExtensionContext, cause: Throwable) { // 测试方法本身执行失败场景会进入该方法 println("测试失败,唯一标识:${context.uniqueId},异常原因:${cause.message}") // 此处添加存储标识的逻辑 } }
调整后不管是测试类本身的方法抛异常,还是扩展回调抛异常导致测试中止,都能正常捕获到对应上下文,拿到测试唯一标识。
如果你需要处理第一个扩展(创建测试数据的扩展)本身的异常,直接在该扩展的回调方法内部加try-catch处理即可,不需要依赖其他扩展的异常处理器。
内容的提问来源于stack exchange,提问作者Bartek Tofel

