Zak*_*rdi 4 kotlin kotlin-coroutines
以下测试成功Process finished with exit code 0
.注意,此测试会将异常打印到日志中,但不会使测试失败(这是我想要的行为).
@Test
fun why_does_this_test_pass() {
val job = launch(Unconfined) {
throw IllegalStateException("why does this exception not fail the test?")
}
// because of `Unconfined` dispatcher, exception is thrown before test function completes
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,这个测试失败了 Process finished with exit code 255
@Test
fun as_expected_this_test_fails() {
throw IllegalStateException("this exception fails the test")
}
Run Code Online (Sandbox Code Playgroud)
为什么这些测试的行为方式不一样?
将您的测试与不使用任何协同程序的测试进行比较,但是开始一个新线程:
@Test
fun why_does_this_test_pass() {
val job = thread { // <-- NOTE: Changed here
throw IllegalStateException("why does this exception not fail the test?")
}
// NOTE: No need for runBlocking any more
job.join() // ensures exception is thrown before test function completes
}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?就像测试一样launch
,如果你运行它,这个测试就会通过,但异常会在控制台上打印出来.
因此,使用launch
启动新协程非常类似于使用thread
启动新线程.如果失败,该错误被在未捕获的异常处理程序处理thread
,并通过CoroutineExceptionHandler
(见它的文档)的launch
.在推出异常不吞咽,但处理由协程异常处理程序.
如果你想例外传播到测试,您应更换launch
与async
和替换join
用await
在你的代码.另请参阅此问题:Kotlin协程中的launch/join和async/await之间有什么区别
更新:Kotlin协程最近引入了"结构化并发"的概念,以避免这种异常丢失.此问题中的代码不再编译.要编译它,你必须明确地说GlobalScope.launch
(如"我确认它可以解除我的异常,这是我的签名")或将测试包装进去runBlocking { ... }
,在这种情况下异常不会丢失.
归档时间: |
|
查看次数: |
982 次 |
最近记录: |