我有 retrofit 服务
interface Service {
@PUT("path")
suspend fun dostuff(@Body body: String)
}
它用于android View 模型。
class VM : ViewModel(private val service: Service){
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
val state = MutableLiveData<String()
init {
uiScope.launch {
service.doStuff()
state.value = "lol"
}
}
override fun onCleared(){
viewModelJob.cancel()
}
}
我想编写一个取消 View 模型的测试。这将通过模拟服务并延迟来完成,以便 co 例程无法完成。在阻塞时,我们调用 onCleared 来取消 co 例程。这应该可以防止状态被设置...
@Test
fun `on cleared - cancels request`() = runBlocking {
//given
`when`(service.doStuff()).thenAnswer { launch { delay(1000) } }
val vm = ViewModel(service)
// when
vm.cleared()
//then
assertThat(vm.state, nullValue())
}
但是 vm.state 似乎总是被设置???清除 co 例程被取消的范围时测试的最佳方法是什么?
最佳答案
这里的问题出在 thenAnswer { launch { delay(1000) } }
中,它实际上使您的 doStuff
方法看起来像这样:
suspend fun doStuff() {
launch { delay(1000) }
}
正如你所看到的,这个函数实际上并没有挂起,它启动了一个协程并立即返回。这里实际起作用的是 thenAnswer {delay(1000) }
,它不起作用,因为 Mockito 中没有 thenAnswer
的挂起版本(据我所知,至少)。
我建议切换到 Mokk模拟库,原生支持 kotlin。然后你可以编写coEvery { doStuff() } coAnswers {delay(1000) }
,它将使你的测试通过(在修复了c的所有语法错误之后)。
关于Android Mockito Kotlin 协程测试取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57878466/