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

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)
    // ...
}
Fredoverflow
quelle
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()
    }
}
Michele d'Amico
quelle
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() {

}
Kirill Rakhman
quelle
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
}
sksamuel
quelle
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 }
    }
}
Frank Neblung
quelle
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
    }
}
Majid
quelle
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")
Yanay Hollander
quelle
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!"))
    }
}
Svetopolk
quelle
0

Eine andere Version der Syntax mit kluent :

@Test
fun `should throw ArithmeticException`() {
    invoking {
        val backHole = 1 / 0
    } `should throw` ArithmeticException::class
}
alexlz
quelle
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()
Cabezas
quelle
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)
Braian Coronel
quelle