Uji pengecualian yang diharapkan di Kotlin


91

Di Java, programmer dapat menentukan pengecualian yang diharapkan untuk kasus uji JUnit seperti ini:

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

Bagaimana saya melakukan ini di Kotlin? Saya telah mencoba dua variasi sintaks, tetapi tidak ada yang berhasil:

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

Jawaban:


126

Terjemahan Kotlin dari contoh Java untuk JUnit 4.12 adalah:

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

Namun, JUnit 4.13 memperkenalkan dua assertThrowsmetode untuk cakupan pengecualian yang lebih terperinci:

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

Kedua assertThrowsmetode mengembalikan pengecualian yang diharapkan untuk pernyataan tambahan:

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

79

Kotlin memiliki paket pembantu pengujiannya sendiri yang dapat membantu melakukan jenis unittest ini.

Tes Anda bisa sangat ekspresif dengan menggunakan assertFailWith:

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

1
Jika mendapatkan 404 pada link Anda, apakah kotlin.testtelah diganti dengan yang lain?
fredoverflow

@fredoverflow Tidak, tidak diganti, tetapi baru saja dihapus dari pustaka standar. Saya telah memperbarui tautan ke repositori github kotlin tetapi sayangnya saya tidak dapat menemukan tautan apa pun ke dokumentasi. Anyway jar dikirimkan oleh kotlin-plugin di intelliJ atau Anda dapat menemukannya di internet atau menambahkan ketergantungan maven / grandle ke proyek Anda.
Michele d'Amico

7
kompilasi "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 mengembalikan pengecualian dan Anda dapat menggunakannya untuk menulis assert Anda sendiri.
Michele d'Amico

26

Anda dapat menggunakan @Test(expected = ArithmeticException::class)atau bahkan lebih baik dari salah satu metode library Kotlin seperti failsWith().

Anda dapat membuatnya lebih pendek dengan menggunakan obat generik yang telah direifikasi dan metode pembantu seperti ini:

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

Dan contoh menggunakan anotasi:

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

}

javaClass<T>()sudah usang sekarang. Gunakan MyException::class.javasebagai gantinya.
puasa

FailWith tidak digunakan lagi, assertFailsWith harus digunakan sebagai gantinya.
gvlasov

15

Anda dapat menggunakan KotlinTest untuk ini.

Dalam pengujian Anda, Anda dapat membungkus kode arbiter dengan blok shouldThrow:

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

Sepertinya garis itu tidak bekerja dengan cara yang benar. Saya centang 1. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe true} - green 2. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe false} - green someMethod () throw "java .lang.AssertionError: message "jika seharusnya, dan mengembalikan objek jika OK. Dalam kedua kasus, shouldThrow berwarna hijau saat OK dan saat TIDAK.
Ivan Trechyokas

Mungkin lihat dokumentasinya, mungkin sudah berubah sejak jawaban saya di 2016. github.com/kotlintest/kotlintest/blob/master/doc/…
sksamuel

13

JUnit5 memiliki dukungan kotlin bawaan .

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
Ini adalah jawaban pilihan saya. Jika Anda mendapatkan Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6assertThrows, pastikan build.gradle Anda memilikicompileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
Big Pumpkin

11

Anda juga dapat menggunakan obat generik dengan paket kotlin.test:

import kotlin.test.assertFailsWith 

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

1

Tegaskan ekstensi yang memverifikasi kelas pengecualian dan juga jika pesan kesalahan cocok.

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

}

sebagai contoh:

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

1

Tidak ada yang menyebutkan bahwa assertFailsWith () mengembalikan nilai dan Anda dapat memeriksa atribut pengecualian:

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

0

Versi lain dari sintaksis menggunakan kluent :

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

0

Langkah pertama adalah menambahkan (expected = YourException::class)anotasi tes

@Test(expected = YourException::class)

Langkah kedua adalah menambahkan fungsi ini

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

Akhirnya Anda akan mendapatkan sesuatu seperti ini:

@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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.