junit中测试指定异常的推荐方式是assertthrows(junit 5)或@test(expected=)(junit 4简单场景),前者类型安全且支持深度校验,后者仅验证异常类型;应避免手动try-catch+fail()。

在 JUnit 中,用 @Test 结合异常断言测试“是否抛出指定异常”,关键在于**让测试框架明确知道“抛出该异常 = 成功”**,而不是靠手动 try-catch 模糊处理。否则 IntelliJ 会把异常当作测试失败,且无法验证异常细节。
JUnit 5 推荐方式:assertThrows(类型安全 + 可深度校验)
这是目前最清晰、最健壮的做法。它返回捕获的异常对象,后续可直接断言其类型、消息、错误码等属性:
- 必须静态导入:
import static org.junit.jupiter.api.Assertions.*; - 写法示例:
@Test void testParseInvalidRequest() { HttpParsingException e = assertThrows(HttpParsingException.class, () -> { httpParser.parseHttpRequest("GETX / HTTP/1.1"); }); assertEquals(HttpStatusCode.SERVER_ERROR_501_NOT_IMPLEMENTED, e.getErrorCode()); assertTrue(e.getMessage().contains("unsupported method")); } - 若未抛出
HttpParsingException,测试立刻失败,并提示 “Expected HttpParsingException to be thrown”;IntelliJ 显示绿色 ✔️
JUnit 4 基础方式:@Test(expected = …)
适用于仅需验证异常类型的简单场景,语法简洁但能力有限:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 写法示例:
@Test(expected = IllegalArgumentException.class) void testMultiplyByZero() { calculator.multiply(5, 0); } - 优点:一行声明,语义明确;IDE 和 Maven 均能正确识别为通过
- 缺点:无法检查异常消息、错误码、cause 等任何内容;若方法中其他位置(如 setup 阶段)也抛同类型异常,测试可能误通过
JUnit 4 进阶方式:ExpectedException Rule(可校验消息与匹配器)
比 @Test(expected=) 更精准,支持对异常消息做字符串或 Hamcrest 匹配:
- 需声明 Rule:
@Rule public ExpectedException thrown = ExpectedException.none();
- 写法示例:
@Test void testInvalidPasswordMessage() { thrown.expect(InvalidPasswordException.class); thrown.expectMessage("at least 6 letters"); Password.validate("123"); } - 注意:该 Rule 已在 JUnit 5 中被弃用,仅限 JUnit 4 项目使用
不推荐的手动 try-catch + fail()
这种写法容易出错,且 IDE 无法识别测试意图:
- 常见错误:漏写
fail(),或把它放在try块末尾导致未执行 - 逻辑混乱:异常被 catch 后未传播,JUnit 认为测试“正常结束”,但实际应失败的地方没暴露出来
- IDE 行为异常:IntelliJ 往往将整个测试标为红色(失败),即使你 catch 了并做了断言
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










