Testen Sie die erwarteten Ausnahmen in Kotlin


90

In Java kann der Programmierer erwartete Ausnahmen für JUnit-Testfälle wie folgt angeben:

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

Wie würde ich das in Kotlin machen? Ich habe zwei Syntaxvarianten ausprobiert, aber keine davon hat funktioniert:

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 ')'

Antworten:


125

Die Kotlin-Übersetzung des Java-Beispiels für JUnit 4.12 lautet:

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

In JUnit 4.13 wurden jedoch zwei assertThrowsMethoden für feinkörnigere Ausnahmebereiche eingeführt:

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

Beide assertThrowsMethoden geben die erwartete Ausnahme für zusätzliche Zusicherungen zurück:

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

79

Kotlin hat ein eigenes Test-Helfer-Paket , das dabei helfen kann, diese Art von Unittest zu tun.

Ihr Test kann durch die Verwendung sehr aussagekräftig sein assertFailWith:

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

1
Wenn Sie einen 404 auf Ihren Link bekommen, wurde kotlin.tester durch etwas anderes ersetzt?
Fredoverflow

@fredoverflow Nein, wird nicht ersetzt, sondern nur aus Standardbibliotheken entfernt. Ich habe den Link zum Github Kotlin Repository aktualisiert, kann aber leider keinen Link zur Dokumentation finden. Wie auch immer, jar wird per Kotlin-Plugin in IntelliJ ausgeliefert oder Sie können es im Internet finden oder Ihrem Projekt eine Maven / Grandle-Abhängigkeit hinzufügen.
Michele d'Amico

7
kompiliere "org.jetbrains.kotlin: kotlin-test: $ kotlin_version"
mac229

4
@ mac229 s / compile / testCompile /
Laurence Gonsalves

@AshishSharma: kotlinlang.org/api/latest/kotlin.test/kotlin.test/… assertFailWith gibt die Ausnahme zurück und Sie können sie verwenden, um Ihre eigene Behauptung zu schreiben.
Michele d'Amico

26

Sie können @Test(expected = ArithmeticException::class)eine der Kotlin-Bibliotheksmethoden wie oder besser verwenden failsWith().

Sie können es noch kürzer machen, indem Sie reifizierte Generika und eine Hilfsmethode wie diese verwenden:

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

Und Beispiel mit der Anmerkung:

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

}

javaClass<T>()ist jetzt veraltet. Verwenden Sie MyException::class.javastattdessen.
Fasth

failWith ist veraltet, assertFailsWith sollte stattdessen verwendet werden.
Gvlasov

15

Sie können dafür KotlinTest verwenden .

In Ihrem Test können Sie beliebigen Code mit einem shouldThrow-Block umschließen:

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

scheint Linie es funktioniert nicht richtig. Ich überprüfe 1. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe true} - grün 2. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe false} - grün someMethod () throw "java .lang.AssertionError: message "wann es sollte, und Objekt zurückgeben, wenn OK. In beiden Fällen sollte shouldThrow grün sein, wenn OK und wenn NICHT.
Ivan Trechyokas

Vielleicht bei der Dokumentation einen Blick darauf werfen, könnte es da meine Antwort im Jahr 2016 geändert github.com/kotlintest/kotlintest/blob/master/doc/...
sksamuel

13

JUnit5 verfügt über eine integrierte Kotlin-Unterstützung .

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
Dies ist meine bevorzugte Antwort. Wenn Sie Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6auf assertThrows kommen, stellen Sie sicher, dass Ihre build.gradle hatcompileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
Big Pumpkin

11

Sie können Generika auch mit dem Paket kotlin.test verwenden:

import kotlin.test.assertFailsWith 

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

1

Assert-Erweiterung, die die Ausnahmeklasse überprüft und auch, ob die Fehlermeldung übereinstimmt.

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}")

}}

zum Beispiel:

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

1

Niemand hat erwähnt, dass assertFailsWith () den Wert zurückgibt und Sie Ausnahmeattribute überprüfen können:

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

0

Eine andere Version der Syntax mit kluent :

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

0

Firt Schritte ist hinzuzufügen , (expected = YourException::class)in Test Annotation

@Test(expected = YourException::class)

Der zweite Schritt besteht darin, diese Funktion hinzuzufügen

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

Endlich haben Sie so etwas:

@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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.