Contents

AssertJ 对异常执行断言

1. 概述

在这个快速教程中,我们将了解AssertJ 的 异常专用断言。

2. 没有AssertJ

为了测试是否抛出了异常,我们需要捕获异常然后执行断言:

try {
    // ...
} catch (Exception e) {
    // assertions
}

但是,如果没有抛出异常怎么办?在这种情况下,测试将通过;这就是为什么必须手动失败测试用例的原因。

3. 使用 AssertJ

使用 Java 8,我们可以通过利用 AssertJ 和 lambda 表达式轻松地对异常进行断言。

3.1. 使用assertThatThrownBy()

让我们检查索引列表中的越界项是否会引发IndexOutOfBoundsException

assertThatThrownBy(() -> {
    List<String> list = Arrays.asList("String one", "String two");
    list.get(2);
}).isInstanceOf(IndexOutOfBoundsException.class)
  .hasMessageContaining("Index: 2, Size: 2");

注意可能引发异常的代码片段是如何作为 lambda 表达式传递的。

当然,我们可以在这里利用各种标准 AssertJ 断言,例如:

.hasMessage("Index: %s, Size: %s", 2, 2)
.hasMessageStartingWith("Index: 2")
.hasMessageContaining("2")
.hasMessageEndingWith("Size: 2")
.hasMessageMatching("Index: \\d+, Size: \\d+")
.hasCauseInstanceOf(IOException.class)
.hasStackTraceContaining("java.io.IOException");

3.2. 使用assertThatExceptionOfType

思路和上面的例子差不多,但是我们可以在开头指定异常类型:

assertThatExceptionOfType(IndexOutOfBoundsException.class)
  .isThrownBy(() -> {
      // ...
}).hasMessageMatching("Index: \\d+, Size: \\d+");

3.3. 使用assertThatIOException和其他常见类型

AssertJ 为常见的异常类型提供了包装器,例如:

assertThatIOException().isThrownBy(() -> {
    // ...
});

同样:

  • assertThatIllegalArgumentException()
  • assertThatIllegalStateException()
  • assertThatIOException()
  • assertThatNullPointerException()

3.4. 将异常与断言分开

编写单元测试的另一种方法是在单独的部分中编写whenthen逻辑:

// when
Throwable thrown = catchThrowable(() -> {
    // ...
});
// then
assertThat(thrown)
  .isInstanceOf(ArithmeticException.class)
  .hasMessageContaining("/ by zero");