在 Kotlin 中测试预期异常
Test expected exceptions in Kotlin
在 Java 中,程序员可以像这样为 JUnit 测试用例指定预期的异常:
@Test(expected = ArithmeticException.class)
public void omg()
{
int blackHole = 1 / 0;
}
我如何在 Kotlin 中执行此操作?我尝试了两种语法变体,但其中 none 有效:
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 ')'
您可以使用 @Test(expected = ArithmeticException::class)
或更好的 Kotlin 库方法之一,例如 failsWith()
.
您可以使用具体化的泛型和像这样的辅助方法使它更短:
inline fun <reified T : Throwable> failsWithX(noinline block: () -> Any) {
kotlin.test.failsWith(javaClass<T>(), block)
}
以及使用注释的示例:
@Test(expected = ArithmeticException::class)
fun omg() {
}
Java 示例 JUnit 4.12 的 Kotlin 翻译是:
@Test(expected = ArithmeticException::class)
fun omg() {
val blackHole = 1 / 0
}
但是,JUnit 4.13 introduced 两个 assertThrows
方法用于更细粒度的异常范围:
@Test
fun omg() {
// ...
assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
// ...
}
两种assertThrows
方法return额外断言的预期异常:
@Test
fun omg() {
// ...
val exception = assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
assertEquals("/ by zero", exception.message)
// ...
}
Kotlin has its own test helper package 可以帮助进行这种单元测试。
你的测试可以通过使用 assertFailWith
:
@Test
fun test_arithmethic() {
assertFailsWith<ArithmeticException> {
omg()
}
}
您可以使用 Kotest 来实现。
在您的测试中,您可以使用 shouldThrow 块包装任意代码:
shouldThrow<ArithmeticException> {
// code in here that you expect to throw a ArithmeticException
}
您还可以将泛型与 kotlin.test 包一起使用:
import kotlin.test.assertFailsWith
@Test
fun testFunction() {
assertFailsWith<MyException> {
// The code that will throw MyException
}
}
JUnit5 内置了 kotlin support。
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 }
}
}
另一个语法版本使用 kluent:
@Test
fun `should throw ArithmeticException`() {
invoking {
val backHole = 1 / 0
} `should throw` ArithmeticException::class
}
断言验证异常的扩展 class 以及错误消息是否匹配。
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")
第一步是在测试注解中添加(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()
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)
没有人提到 assertFailsWith() returns 值,您可以检查异常属性:
@Test
fun `my test`() {
val exception = assertFailsWith<MyException> {method()}
assertThat(exception.message, equalTo("oops!"))
}
}
这个简单的示例适用于 Junit 的 4.13.2 版本
@Test
fun testZeroDividing(){
var throwing = ThrowingRunnable { /*call your method here*/ Calculator().divide(1,0) }
assertThrows(/*define your exception here*/ IllegalArgumentException::class.java, throwing)
}
在 Java 中,程序员可以像这样为 JUnit 测试用例指定预期的异常:
@Test(expected = ArithmeticException.class)
public void omg()
{
int blackHole = 1 / 0;
}
我如何在 Kotlin 中执行此操作?我尝试了两种语法变体,但其中 none 有效:
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 ')'
您可以使用 @Test(expected = ArithmeticException::class)
或更好的 Kotlin 库方法之一,例如 failsWith()
.
您可以使用具体化的泛型和像这样的辅助方法使它更短:
inline fun <reified T : Throwable> failsWithX(noinline block: () -> Any) {
kotlin.test.failsWith(javaClass<T>(), block)
}
以及使用注释的示例:
@Test(expected = ArithmeticException::class)
fun omg() {
}
Java 示例 JUnit 4.12 的 Kotlin 翻译是:
@Test(expected = ArithmeticException::class)
fun omg() {
val blackHole = 1 / 0
}
但是,JUnit 4.13 introduced 两个 assertThrows
方法用于更细粒度的异常范围:
@Test
fun omg() {
// ...
assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
// ...
}
两种assertThrows
方法return额外断言的预期异常:
@Test
fun omg() {
// ...
val exception = assertThrows(ArithmeticException::class.java) {
val blackHole = 1 / 0
}
assertEquals("/ by zero", exception.message)
// ...
}
Kotlin has its own test helper package 可以帮助进行这种单元测试。
你的测试可以通过使用 assertFailWith
:
@Test
fun test_arithmethic() {
assertFailsWith<ArithmeticException> {
omg()
}
}
您可以使用 Kotest 来实现。
在您的测试中,您可以使用 shouldThrow 块包装任意代码:
shouldThrow<ArithmeticException> {
// code in here that you expect to throw a ArithmeticException
}
您还可以将泛型与 kotlin.test 包一起使用:
import kotlin.test.assertFailsWith
@Test
fun testFunction() {
assertFailsWith<MyException> {
// The code that will throw MyException
}
}
JUnit5 内置了 kotlin support。
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 }
}
}
另一个语法版本使用 kluent:
@Test
fun `should throw ArithmeticException`() {
invoking {
val backHole = 1 / 0
} `should throw` ArithmeticException::class
}
断言验证异常的扩展 class 以及错误消息是否匹配。
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")
第一步是在测试注解中添加(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()
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)
没有人提到 assertFailsWith() returns 值,您可以检查异常属性:
@Test
fun `my test`() {
val exception = assertFailsWith<MyException> {method()}
assertThat(exception.message, equalTo("oops!"))
}
}
这个简单的示例适用于 Junit 的 4.13.2 版本
@Test
fun testZeroDividing(){
var throwing = ThrowingRunnable { /*call your method here*/ Calculator().divide(1,0) }
assertThrows(/*define your exception here*/ IllegalArgumentException::class.java, throwing)
}