1. 概述

在 Kotlin 开发中,测试异常是我们验证程序健壮性的重要手段。Kotlin 提供了内置的方法 assertFailsWith,可以帮助我们优雅地测试代码是否按预期抛出异常。

本文将介绍如何使用 JUnit 5 和 Kotlin 标准库中的 assertFailsWith 方法来测试异常,并通过示例代码说明其使用场景和注意事项。

2. 使用 JUnit 5 测试异常

JUnit 5 是 Java 和 Kotlin 项目中最常用的测试框架之一。它提供了丰富的断言方法来验证测试结果,其中就包括异常断言。

JUnit 5 提供了一个非常实用的方法:assertThrows(),用于验证某个代码块是否抛出了指定类型的异常。

✅ 示例代码如下:

fun whenInvalidArray_thenThrowsException() {
    assertThrows<ArrayIndexOutOfBoundsException> {
        val array = intArrayOf(1, 2, 3)
        array[5] // 越界访问
    }
}

这段代码中,我们期望访问数组越界时抛出 ArrayIndexOutOfBoundsException,如果抛出该异常或其子类的实例,测试就会通过。

⚠️ 注意:assertThrows() 会返回捕获到的异常对象,我们可以进一步验证其属性。

3. 使用 Kotlin 的 assertFailsWith 方法

除了 JUnit 5,Kotlin 标准库也提供了一个原生的异常测试方法:assertFailsWith,它功能更简洁、使用更轻量。

这个方法允许我们验证一个代码块是否抛出了指定类型的异常。它有多个重载版本,支持传入异常类型、错误信息和执行代码块。

✅ 基本用法如下:

fun givenInvalidArray_thenThrowsException() {
    assertFailsWith<ArrayIndexOutOfBoundsException>(
        message = "No exception found",
        block = {
            val array = intArrayOf(1, 2, 3)
            array[5]
        }
    )
}

在这个例子中,如果代码块抛出了 ArrayIndexOutOfBoundsException,测试通过;否则显示我们自定义的提示信息 "No exception found"

3.1. 指定异常类型

我们也可以通过 exceptionClass 参数显式指定期望的异常类型:

fun givenInvalidFormat_thenThrowsException() {
    assertFailsWith(
        exceptionClass = NumberFormatException::class,
        block = { "Kotlin Tutorials in Baeldung".toInt() }
    )
}

如果代码块抛出的不是 NumberFormatException,即使它是其父类(如 IllegalArgumentException),测试也会失败。

3.2. 验证异常消息

assertFailsWith 返回异常对象,我们可以用它进一步验证异常的属性,例如 message

fun givenInvalidNumericFormat_thenThrowsException() {
    val exception = assertFailsWith<NumberFormatException> {
        Integer.parseInt("abcdefgh")
    }
    assertThat(exception.message, equalTo("For input string: \"abcdefgh\""))
}

✅ 这样我们不仅可以验证异常类型,还能验证异常信息是否符合预期。

⚠️ 踩坑提醒:虽然 assertFailsWith 可以捕获子类异常,但建议始终使用最具体的异常类型,避免使用 ExceptionRuntimeException,否则容易掩盖真实问题。

3.3. 优势对比

特性 assertFailsWith assertThrows (JUnit 5)
是否需要引入额外依赖 ❌ 不需要 ✅ 需要引入 JUnit 5
是否返回异常对象 ✅ 是 ✅ 是
使用是否简洁 ✅ 是 ✅ 是
适用场景 单一异常断言 多断言组合测试

✅ 如果你只是想快速测试一段代码是否抛出异常,推荐使用 assertFailsWith;如果你的测试逻辑更复杂,涉及多个断言,那 JUnit 的 assertThrows() 更适合。

4. 总结

本文介绍了在 Kotlin 中使用 assertFailsWith 和 JUnit 5 的 assertThrows() 方法测试异常的方式。

  • assertFailsWith 是 Kotlin 标准库提供的方法,无需引入额外依赖,适用于简单异常测试。
  • JUnit 5 的 assertThrows() 更适合复杂测试场景,尤其在组合多个断言时更有优势。
  • 无论使用哪种方式,都建议指定具体的异常类型,并验证异常属性,以提升测试的准确性。

如需了解更多 Kotlin 特性,请参考我们的 Kotlin 教程


原始标题:Testing Exceptions in Kotlin with assertFailsWith