在Kotlin中测试预期的异常


91

在Java中,程序员可以为JUnit测试用例指定预期的异常,如下所示:

@Test(expected = ArithmeticException.class)
public void omg()
{
    int blackHole = 1 / 0;
}

我将如何在Kotlin中做到这一点?我尝试了两种语法变体,但没有一个起作用:

import org.junit.Test

// ...

@Test(expected = ArithmeticException) fun omg()
    Please specify constructor invocation;
    classifier 'ArithmeticException' does not have a companion object

@Test(expected = ArithmeticException.class) fun omg()
                            name expected ^
                                            ^ expected ')'

Answers:


126

JUnit 4.12的Java示例的Kotlin转换为:

@Test(expected = ArithmeticException::class)
fun omg() {
    val blackHole = 1 / 0
}

但是,JUnit 4.13 引入了两种assertThrows用于更细粒度异常范围的方法:

@Test
fun omg() {
    // ...
    assertThrows(ArithmeticException::class.java) {
        val blackHole = 1 / 0
    }
    // ...
}

这两种assertThrows方法都将为其他断言返回预期的异常:

@Test
fun omg() {
    // ...
    val exception = assertThrows(ArithmeticException::class.java) {
        val blackHole = 1 / 0
    }
    assertEquals("/ by zero", exception.message)
    // ...
}

79

Kotlin有自己的测试帮助程序包,可以帮助您进行这种单元测试

通过使用,您的测试可以非常有表现力assertFailWith

@Test
fun test_arithmethic() {
    assertFailsWith<ArithmeticException> {
        omg()
    }
}

1
如果您的链接上显示404,是否kotlin.test已被其他内容替换?
fredoverflow

@fredoverflow否,不会被替换,而只是从标准库中删除。我已经更新了指向github kotlin存储库的链接,但是不幸的是我找不到任何指向文档的链接。无论如何,jar是由intelliJ中的kotlin-plugin附带提供的,或者您可以在网上找到它,或者将maven / grandle依赖项添加到您的项目中。
米歇尔·达米科

7
编译“ org.jetbrains.kotlin:kotlin-test:$ kotlin_version”
mac229 2009年

4
@ mac229 s / compile / testCompile /
劳伦斯·贡萨尔维斯

@AshishSharma:kotlinlang.org/api/latest/kotlin.test/kotlin.test/…assertFailWith返回异常,您可以使用它编写自己的断言。
米歇尔·达米科

26

您可以使用@Test(expected = ArithmeticException::class)甚至更好的Kotlin的库方法之一,例如failsWith()

您可以通过使用通用化泛型和类似如下的辅助方法来使其更短:

inline fun <reified T : Throwable> failsWithX(noinline block: () -> Any) {
    kotlin.test.failsWith(javaClass<T>(), block)
}

以及使用注释的示例:

@Test(expected = ArithmeticException::class)
fun omg() {

}

javaClass<T>()现在已弃用。使用MyException::class.java代替。
fasth 2015年

failsWith已过时,assertFailsWith应改为使用。
gvlasov 2015年

15

您可以为此使用KotlinTest

在您的测试中,您可以使用shouldThrow块包装任意代码:

shouldThrow<ArithmeticException> {
  // code in here that you expect to throw a ArithmeticException
}

似乎行无法正常工作。我检查了1. ShouldThrow <java.lang.AssertionError> {someMethod()。isOK应该是}-绿色2. ShouldThrow <java.lang.AssertionError> {someMethod()。isOK应该是false}-绿色someMethod()抛出“ .lang.AssertionError:message”,如果可以,则返回对象。在这两种情况下,当正常和非正常时,throwThrow均为绿色。
伊万·特雷基卡斯

也许看看文档,自2016年我的回答以来,它可能已经更改。github.com
kotlintest/

13

JUnit5具有内置的kotlin支持

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

class MyTests {
    @Test
    fun `division by zero -- should throw ArithmeticException`() {
        assertThrows<ArithmeticException> {  1 / 0 }
    }
}

3
这是我的首选答案。如果您Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6使用assertThrows,请确保您的build.gradle具有compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
Big Pumpkin

11

您还可以将泛型与kotlin.test包一起使用:

import kotlin.test.assertFailsWith 

@Test
fun testFunction() {
    assertFailsWith<MyException> {
         // The code that will throw MyException
    }
}

1

声明扩展,以验证异常类以及错误消息是否匹配。

inline fun <reified T : Exception> assertThrows(runnable: () -> Any?, message: String?) {
try {
    runnable.invoke()
} catch (e: Throwable) {
    if (e is T) {
        message?.let {
            Assert.assertEquals(it, "${e.message}")
        }
        return
    }
    Assert.fail("expected ${T::class.qualifiedName} but caught " +
            "${e::class.qualifiedName} instead")
}
Assert.fail("expected ${T::class.qualifiedName}")

}

例如:

assertThrows<IllegalStateException>({
        throw IllegalStateException("fake error message")
    }, "fake error message")

1

没有人提到assertFailsWith()返回值,您可以检查异常属性:

@Test
fun `my test`() {
        val exception = assertFailsWith<MyException> {method()}
        assertThat(exception.message, equalTo("oops!"))
    }
}

0

语法的另一个版本使用kluent

@Test
fun `should throw ArithmeticException`() {
    invoking {
        val backHole = 1 / 0
    } `should throw` ArithmeticException::class
}

0

首要步骤是添加(expected = YourException::class)测试注释

@Test(expected = YourException::class)

第二步是添加此功能

private fun throwException(): Boolean = throw YourException()

最终,您将获得以下内容:

@Test(expected = ArithmeticException::class)
fun `get query error from assets`() {
    //Given
    val error = "ArithmeticException"

    //When
    throwException()
    val result =  omg()

    //Then
    Assert.assertEquals(result, error)
}
private fun throwException(): Boolean = throw ArithmeticException()

0

org.junit.jupiter.api.Assertions.kt

/**
 * Example usage:
 * ```kotlin
 * val exception = assertThrows<IllegalArgumentException>("Should throw an Exception") {
 *     throw IllegalArgumentException("Talk to a duck")
 * }
 * assertEquals("Talk to a duck", exception.message)
 * ```
 * @see Assertions.assertThrows
 */
inline fun <reified T : Throwable> assertThrows(message: String, noinline executable: () -> Unit): T =
        assertThrows({ message }, executable)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.