You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:07:26