Kiểm tra các ngoại lệ dự kiến ​​trong Kotlin


91

Trong Java, lập trình viên có thể chỉ định các ngoại lệ dự kiến ​​cho các trường hợp thử nghiệm JUnit như sau:

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

Tôi sẽ làm điều này như thế nào trong Kotlin? Tôi đã thử hai biến thể cú pháp, nhưng không có biến thể nào trong số chúng hoạt động:

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

Câu trả lời:


126

Bản dịch Kotlin của ví dụ Java cho JUnit 4.12 là:

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

Tuy nhiên, JUnit 4.13 đã giới thiệu hai assertThrowsphương pháp cho các phạm vi ngoại lệ chi tiết hơn:

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

Cả hai assertThrowsphương pháp đều trả về ngoại lệ mong đợi cho các xác nhận bổ sung:

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

80

Kotlin có gói trình trợ giúp kiểm tra của riêng mình có thể giúp thực hiện loại thú vị nhất này.

Bài kiểm tra của bạn có thể rất biểu cảm bằng cách sử dụng assertFailWith:

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

1
Nếu nhận được 404 trên liên kết của bạn, đã kotlin.testđược thay thế bằng một cái gì đó khác?
fredoverflow

@fredoverflow Không, không được thay thế mà chỉ bị xóa khỏi các thư viện tiêu chuẩn. Tôi đã cập nhật liên kết đến kho lưu trữ github kotlin nhưng tiếc là tôi không thể tìm thấy bất kỳ liên kết nào đến tài liệu. Dù sao thì jar được vận chuyển bằng kotlin-plugin trong intelliJ hoặc bạn có thể tìm thấy nó trên mạng hoặc thêm phụ thuộc maven / grandle vào dự án của bạn.
Michele d'Amico

7
biên dịch "org.jetbrains.kotlin: kotlin-test: $ kotlin_version"
mac229 21/09/17

4
@ mac229 s / biên dịch / testCompile /
Laurence Gonsalves

@AshishSharma: kotlinlang.org/api/latest/kotlin.test/kotlin.test/… khẳng địnhFailVới việc trả về ngoại lệ và bạn có thể sử dụng nó để viết khẳng định của riêng mình.
Michele d'Amico

26

Bạn có thể sử dụng @Test(expected = ArithmeticException::class)hoặc thậm chí tốt hơn một trong các phương pháp thư viện của Kotlin như failsWith().

Bạn có thể làm cho nó ngắn hơn nữa bằng cách sử dụng các generic đã được sửa đổi và một phương pháp trợ giúp như sau:

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

Và ví dụ bằng cách sử dụng chú thích:

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

}

javaClass<T>()hiện không được dùng nữa. Sử dụng MyException::class.javathay thế.
fasth

failWith không được dùng nữa, thì sẽ được dùng statementFailsWith để thay thế.
gvlasov

15

Bạn có thể sử dụng KotlinTest cho việc này.

Trong thử nghiệm của mình, bạn có thể bọc mã trọng tài bằng khối shouldThrow:

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

có vẻ như dòng nó không hoạt động theo cách thích hợp. Tôi kiểm tra 1. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe true} - xanh lục 2. shouldThrow <java.lang.AssertionError> {someMethod (). IsOK shouldBe false} - xanh someMethod () ném "java .lang.AssertionError: thông báo "khi cần, và trả về đối tượng nếu OK. Trong cả hai trường hợp, shouldThrow có màu xanh lục khi OK và khi KHÔNG.
Ivan Trechyokas

Có lẽ hãy nhìn vào các tài liệu, nó có thể đã thay đổi kể từ khi câu trả lời của tôi trong năm 2016. github.com/kotlintest/kotlintest/blob/master/doc/...
sksamuel

13

JUnit5 có hỗ trợ kotlin được tích hợp sẵn.

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
Đây là câu trả lời ưa thích của tôi. Nếu bạn nhận được Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target 1.6trên assertThrows, hãy chắc chắn bạn có build.gradlecompileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
Big Pumpkin

11

Bạn cũng có thể sử dụng generic với gói kotlin.test:

import kotlin.test.assertFailsWith 

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

1

Phần mở rộng xác nhận xác minh lớp ngoại lệ và cả khi thông báo lỗi khớp.

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

}

ví dụ:

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

1

Không ai đề cập rằng khẳng định FailsWith () trả về giá trị và bạn có thể kiểm tra các thuộc tính ngoại lệ:

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

0

Một phiên bản khác của cú pháp sử dụng kluent :

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

0

Bước Firt là thêm (expected = YourException::class)vào chú thích thử nghiệm

@Test(expected = YourException::class)

Bước thứ hai là thêm chức năng này

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

Cuối cùng bạn sẽ có một cái gì đó như thế này:

@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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.