1. 引言
在使用 JUnit 编写单元测试时,我们经常会看到两种失败类型:Failure(断言失败) 和 Error(异常错误)。
虽然它们都表示测试未通过,但语义上有明显区别:
✅ Failure:表示预期断言未满足,说明代码逻辑有问题
❌ Error:表示测试过程中出现了未处理的异常,比如空指针、除以零等
理解这两者的区别有助于我们更快定位问题所在,避免踩坑。
2. 示例代码
我们以一个简单的 SimpleCalculator
类为例,其中包含一个 divideNumbers
方法用于对两个 double
数进行除法运算:
public class SimpleCalculator {
public static double divideNumbers(double dividend, double divisor) {
if (divisor == 0) {
throw new ArithmeticException("Division by zero!");
}
return dividend / divisor;
}
}
⚠️ 注意:Java 在 double
类型除以零时并不会抛出异常,而是返回 Infinity
或 NaN
。我们这里手动添加了抛出异常的逻辑,是为了更直观地演示 Error 的情况。
3. 示例:Failure
当我们使用 JUnit 编写单元测试时,最常见的情况是测试失败(Failure)。这通常是因为代码没有达到预期结果,即断言未通过。
例如下面这个测试方法:
@Test
void whenDivideNumbers_thenExpectWrongResult() {
double result = SimpleCalculator.divideNumbers(6, 3);
assertEquals(15, result);
}
这段代码中,6 / 3 = 2
,但我们在断言时期望结果是 15
,因此测试失败,JUnit 会报告这是一个 Failure。
✅ 这类问题通常说明你的业务逻辑有误,需要检查代码逻辑是否正确。
4. 示例:Error
除了断言失败外,还有一种情况是测试执行过程中发生了异常,导致测试无法正常完成,这类情况称为 Error。
比如我们测试除以零的情况:
@Test
void whenDivideByZero_thenThrowsException() {
SimpleCalculator.divideNumbers(10, 0);
}
此时会抛出一个 ArithmeticException
,而测试并没有捕获它,JUnit 会将此标记为一个 Error。
⚠️ 这类问题通常说明测试写得不够严谨,或者代码本身存在未处理的异常路径。
要修复这个问题,我们可以使用 assertThrows
来显式断言异常是否被正确抛出:
@Test
void whenDivideByZero_thenAssertException() {
assertThrows(ArithmeticException.class, () -> SimpleCalculator.divideNumbers(10, 0));
}
✅ 此时如果抛出指定异常,测试通过;否则变成 Failure。
5. 总结
类型 | 含义 | 示例场景 | 说明 |
---|---|---|---|
Failure | 预期结果未满足 | assertEquals(15, result) 失败 |
表示业务逻辑错误 |
Error | 测试执行过程中发生异常 | 除以零抛出异常未处理 | 表示测试或代码存在未处理的异常 |
📌 简单粗暴总结一句话:
Failure 是“断言错了”,Error 是“出事了”。
两者都值得关注,Failure 更偏向逻辑问题,而 Error 更偏向运行时异常处理不全。
完整示例代码可参考 GitHub 仓库。