如何用JUnit捕获并断言私有内部异常?求类似Spock thrown()的方法
JUnit捕获并断言私有内部异常的实用方案
一、JUnit 5 对应Spock thrown()的内置方法
JUnit 5的Assertions.assertThrows()就是替代Spockthrown()的标准方法,但因为RetryExhaustedException是reactor.core.Exceptions的私有静态内部类,无法直接在测试代码中引用该类型,可通过以下两种方式处理:
方案1:反射+assertThrows精准捕获
@Test void exampleTest() throws ClassNotFoundException { // given stubToForce5xxResponse(); // when & then Throwable thrown = Assertions.assertThrows( Class.forName("reactor.core.Exceptions$RetryExhaustedException"), () -> exampleService.exampleMethod() ); Assertions.assertThat(thrown.getMessage()).isEqualTo("Retries exhausted: 3/3"); }
通过Class.forName()获取私有内部类的Class对象,传入assertThrows()实现精准捕获,后续直接断言异常消息即可。
方案2:捕获父类异常后断言类型
如果不想使用反射,可捕获RetryExhaustedException的父类IllegalStateException,再通过类名和消息做精准校验:
@Test void exampleTest() { // given stubToForce5xxResponse(); // when & then IllegalStateException thrown = Assertions.assertThrows( IllegalStateException.class, () -> exampleService.exampleMethod() ); Assertions.assertThat(thrown.getClass().getName()) .isEqualTo("reactor.core.Exceptions$RetryExhaustedException"); Assertions.assertThat(thrown.getMessage()).isEqualTo("Retries exhausted: 3/3"); }
二、Reactor反应式代码的特殊测试方式
如果exampleService.exampleMethod()返回的是Mono或Flux,直接调用方法不会触发执行(Reactor是懒加载模型),此时自定义捕获方法无法拿到异常,必须用Reactor官方测试工具StepVerifier:
import reactor.test.StepVerifier; @Test void exampleReactiveTest() { // given stubToForce5xxResponse(); // when & then StepVerifier.create(exampleService.exampleMethod()) .expectErrorMatches(throwable -> throwable.getClass().getName().equals("reactor.core.Exceptions$RetryExhaustedException") && throwable.getMessage().equals("Retries exhausted: 3/3") ) .verify(); }
这种方式完全适配反应式流的执行逻辑,能准确捕获流中抛出的异常。
三、优化你的自定义捕获方法
如果想保留自己的getExceptionThrown方法,可结合JUnit断言简化校验逻辑:
@Test void exampleTest() throws ClassNotFoundException { // given stubToForce5xxResponse(); // when Throwable ex = getExceptionThrown(() -> exampleService.exampleMethod()); // then Assertions.assertThat(ex) .isNotNull() .extracting(Throwable::getClass, Throwable::getMessage) .containsExactly( Class.forName("reactor.core.Exceptions$RetryExhaustedException"), "Retries exhausted: 3/3" ); } private Throwable getExceptionThrown(Runnable runnable) { try { runnable.run(); return null; } catch (Exception ex) { return ex; } }
内容的提问来源于stack exchange,提问作者Tchorzyksen
相关产品推荐
相关产品推荐

