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

异常被try/catch块捕获时,能否通过@Test注解测试主函数是否抛出指定异常?

问题分析与解决方案

首先直接给出结论:你的测试用例永远不会通过,因为maxSum方法内部已经用try/catch捕获了TooMuchException,这个异常完全被方法内部消化了,不会向外部抛出——assertThatThrownBy只能捕获那些从方法中逃逸出来的异常,所以你的断言逻辑从根本上不成立。

为什么会这样?

看你的业务代码:

public int maxSum(int a, int b) {
    try {
        if (a + b > 100) throw new TooMuchException("Too much! Sum reduced to 50");
    } catch (TooMuchException e) {
        System.out.println(e);
        return 50;
    }
    return a + b;
}

当a+b>100时,确实会抛出TooMuchException,但紧接着就被catch块捕获,方法直接返回50,异常根本不会离开这个方法的作用域。

如何正确测试你的需求?

你的核心需求是:确保函数能捕获异常而不崩溃,同时验证异常触发的逻辑是正确的。可以从以下几个方向入手:

1. 测试返回值(最直接的方式)

既然异常被处理后会返回固定值50,那测试返回值是否符合预期,就能间接验证异常的触发和处理逻辑是正常的:

@Test
void maxSum_returns50WhenSumExceeds100() {
    Service service = new Service();
    int result = service.maxSum(55, 66); // 55+66=121>100
    assertThat(result).isEqualTo(50);
}

@Test
void maxSum_returnsActualSumWhenSumIsWithinLimit() {
    Service service = new Service();
    int result = service.maxSum(45, 50); // 45+50=95≤100
    assertThat(result).isEqualTo(95);
}

这种方式简单直接,完全覆盖了你的业务逻辑:当总和超过阈值时,返回50;否则返回实际总和,同时保证程序不会崩溃。

2. 验证异常确实被触发过(如果需要更细粒度的验证)

如果你一定要确认TooMuchException被抛出过(而不只是验证返回值),可以通过给Service类添加状态标记的方式实现:

public class Service {
    private boolean tooMuchExceptionWasThrown = false;

    public int maxSum(int a, int b) {
        tooMuchExceptionWasThrown = false; // 每次调用重置标记
        try {
            if (a + b > 100) throw new TooMuchException("Too much! Sum reduced to 50");
        } catch (TooMuchException e) {
            tooMuchExceptionWasThrown = true; // 标记异常被触发
            System.out.println(e);
            return 50;
        }
        return a + b;
    }

    // 提供获取标记的方法
    public boolean isTooMuchExceptionWasThrown() {
        return tooMuchExceptionWasThrown;
    }
}

然后编写测试用例验证标记:

@Test
void maxSum_triggersTooMuchExceptionWhenSumOver100() {
    Service service = new Service();
    service.maxSum(55, 66);
    assertThat(service.isTooMuchExceptionWasThrown()).isTrue();
}

@Test
void maxSum_doesNotTriggerExceptionWhenSumUnder100() {
    Service service = new Service();
    service.maxSum(30, 40);
    assertThat(service.isTooMuchExceptionWasThrown()).isFalse();
}

3. 小提示:自定义异常的继承选择

你的TooMuchException继承了Throwable,这在Java中非常少见——通常自定义业务异常应该继承Exception(受检异常)或者RuntimeException(非受检异常)。继承Throwable会让你的异常处理逻辑变得繁琐(比如必须显式声明或捕获),建议调整为:

// 作为受检异常
public class TooMuchException extends Exception {
    public TooMuchException(String message) {
        super(message);
    }
}
// 或者作为非受检异常
public class TooMuchException extends RuntimeException {
    public TooMuchException(String message) {
        super(message);
    }
}

内容的提问来源于stack exchange,提问作者Pewu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 08:42:44