我有一个可挂起的函数,我想断言,在某些情况下,它不会以结果来完成.我try 编写以下扩展,它的目标是在断言作业(job)是否完成之前等待5秒(我认为这个判断足以知道挂起的对象仍处于挂起状态):
First Approach:个
// Extension Function
fun <T> TestScope.assertNotCompleted(block: suspend CoroutineScope.() -> T) {
val result = async { block }
advanceTimeBy(5000L)
val isBlockComplete = result.isCompleted
assertThat(isBlockComplete, equalTo(false))
}
// Usage
@Test
fun `Given no value is ready, when waitForValue is called, then the suspendable function is not complete`() =
runTest {
assertNotCompleted {
someClass.waitForValue()
}
}
然而,在这种情况下,当result.isCompleted
应该为FALSE时,它总是返回TRUE.如果我go 掉advanceTimeBy(5000L)
,那么result.isCompleted
总是返回false
,即使我修改测试以实际返回一些东西.
我试过另一种方法,用getCompletionExceptionOrNull()
投出IllegalStateException
分.这实际上是有效的,但它导致了一个奇怪的接口,在该接口中,我们需要使用"Expect"属性来注释使用它的每个测试.如果可能的话,我想避免这种情况,因为测试中的其他地方可能会抛出异常,因此测试可能会不正确地通过.
Second Approach:个
// Extension Function
@OptIn(ExperimentalCoroutinesApi::class)
fun <T> TestScope.assertNotCompleted(block: suspend CoroutineScope.() -> T) {
async(block = block).run {
this@assertNotCompleted.advanceTimeBy(5000L)
getCompletionExceptionOrNull()
}
}
// Usage - wanting to avoid the need for expected property
@Test(expected = IllegalStateException::class)
fun `Given no value is ready, when waitForValue is called, then the suspendable function is not complete`() =
runTest {
assertNotCompleted {
someClass.waitForValue()
}
}
我确实try 过捕捉这个异常,但是测试要么总是通过,要么总是失败,这取决于advanceTimeBy(5000L)
的位置--这与可挂起的对象能否完成无关.
Thrid Approach:个
// Extension Function
@OptIn(ExperimentalCoroutinesApi::class)
fun <T> TestScope.assertNotCompleted(block: suspend CoroutineScope.() -> T) {
runCatching {
val result = async {
block
// advanceTimeBy(5000L) Test ALWAYS passes
}
// advanceTimeBy(5000L) Test ALWAYS fails
result.getCompletionExceptionOrNull()
}.also {
assertThat(it.isFailure, equalTo(true))
}
}
// Usage is same as first approach
先谢谢你.