ทดสอบข้อยกเว้นที่คาดไว้ใน Kotlin


94

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

คำตอบ:


128

ตัวอย่างการแปล Kotlin ของ Java สำหรับJUnit 4.12คือ:

@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)
    // ...
}

83

Kotlin มีแพ็คเกจผู้ช่วยทดสอบของตัวเองที่สามารถช่วยทำแบบนี้ได้อย่างเต็มที่

การทดสอบของคุณสามารถแสดงออกได้มากโดยใช้assertFailWith:

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

1
หากได้รับ 404 บนลิงค์ของคุณkotlin.testถูกแทนที่ด้วยสิ่งอื่นหรือไม่
fredoverflow

@fredoverflow ไม่ไม่ถูกแทนที่ แต่เพิ่งถูกลบออกจากไลบรารีมาตรฐาน ฉันได้อัปเดตลิงก์ไปยังที่เก็บ github kotlin แล้ว แต่น่าเสียดายที่ฉันไม่พบลิงก์ไปยังเอกสารใด ๆ อย่างไรก็ตาม jar จะถูกจัดส่งโดย kotlin-plugin ใน intelliJ หรือคุณสามารถหาได้จากเน็ตหรือเพิ่ม maven / grandle dependency ในโปรเจ็กต์ของคุณ
Michele d'Amico

7
รวบรวม "org.jetbrains.kotlin: kotlin-test: $ kotlin_version"
mac229

4
@ mac229 s / compile / testCompile /
Laurence Gonsalves

@AshishSharma: kotlinlang.org/api/latest/kotlin.test/kotlin.test/… assertFail พร้อมส่งกลับข้อยกเว้นและคุณสามารถใช้เพื่อเขียนคำยืนยันของคุณเอง
Michele d'Amico

26

คุณสามารถใช้@Test(expected = ArithmeticException::class)หรือดีกว่าวิธีห้องสมุดของ Kotlin เช่นfailsWith() .

คุณสามารถทำให้สั้นลงได้โดยใช้ reified generics และวิธีการช่วยเหลือดังนี้:

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

ล้มเหลวด้วยเลิกใช้แล้ว ควรใช้assertFailsWithแทน
gvlasov

15

คุณสามารถใช้KotlinTestสำหรับสิ่งนี้

ในการทดสอบของคุณคุณสามารถรวมรหัสอนุญาโตตุลาการด้วยบล็อก shouldThrow:

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

ดูเหมือนว่าเส้นจะไม่ทำงานอย่างถูกต้อง ฉันตรวจสอบ 1. shouldThrow <java.lang.AssertionError> {someMethod (). isOK shouldBe true} - สีเขียว 2. shouldThrow <java.lang.AssertionError> {someMethod () isOK shouldBe false} - สีเขียว someMethod () throw "java .lang.AssertionError: ข้อความ "เมื่อควรและส่งคืนวัตถุถ้าตกลง ในทั้งสองกรณีควรโยนเป็นสีเขียวเมื่อตกลงและเมื่อไม่
Ivan Trechyokas

บางทีลองดูที่เอกสารอาจมีการเปลี่ยนแปลงเนื่องจากคำตอบของฉันในปี 2559 github.com/kotlintest/kotlintest/blob/master/doc/…
sksamuel

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.6assertThrows โปรดตรวจสอบว่า 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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.