gpt4 book ai didi

kotlin - Kotlin Flow:测试挂起

转载 作者:行者123 更新时间:2023-12-02 12:40:20 24 4
gpt4 key购买 nike

我正在尝试使用Flows测试Kotlin实现。我使用Kotest进行测试。此代码有效:

ViewModel:

val detectedFlow = flow<String> {
emit("123")
delay(10L)
emit("123")
}

测试:
class ScanViewModelTest : StringSpec({
"when the flow contains values they are emitted" {
val detectedString = "123"
val vm = ScanViewModel()
launch {
vm.detectedFlow.collect {
it shouldBe detectedString
}
}
}
})

但是,在实际的ViewModel中,我需要向流中添加值,因此我使用 ConflatedBroadcastChannel如下:
private val _detectedValues = ConflatedBroadcastChannel<String>()
val detectedFlow = _detectedValues.asFlow()

suspend fun sendDetectedValue(detectedString: String) {
_detectedValues.send(detectedString)
}

然后在测试中,我尝试:
"when the flow contains values they are emitted" {
val detectedString = "123"
val vm = ScanViewModel()
runBlocking {
vm.sendDetectedValue(detectedString)
}
runBlocking {
vm.detectedFlow.collect { it shouldBe detectedString }
}
}

测试只是挂起而从未完成。我尝试了所有事情: launchrunBlockingTest而不是 runBlocking,将发送和收集放在相同或单独的协程中, offer而不是 send ...似乎什么都无法解决。我究竟做错了什么?

更新:如果我手动创建流程,则可以:
private val _detectedValues = ConflatedBroadcastChannel<String>()
val detectedFlow = flow {
this.emit(_detectedValues.openSubscription().receive())
}

那么,这是 asFlow()方法中的错误吗?

最佳答案

问题在于您在测试中使用的collect函数是一个暂停函数,它将暂停执行直到Flow完成。

在第一个示例中,您的detectedFlow是有限的。它只会发出两个值并完成。在问题更新中,您还将创建一个有限流,该流将发出单个值并完成。这就是为什么您的测试有效的原因。

但是,在第二个示例(实际示例)中,该流程是从一个从未关闭的ConflatedBroadcastChannel 创建的。因此,collect函数将永远暂停执行。为了使测试正常进行而不会永远阻塞线程,您还需要使流有限。我通常为此使用first()运算符。另一种选择是对close进行ConflatedBroadcastChannel编码,但这通常意味着仅出于测试目的就对代码进行了修改,这不是一个好习惯。

这就是您的测试与first()运算符一起工作的方式

"when the flow contains values they are emitted" {
val detectedString = "123"
val vm = ScanViewModel()
runBlocking {
vm.sendDetectedValue(detectedString)
}
runBlocking {
vm.detectedFlow.first() shouldBe detectedString
}
}

关于kotlin - Kotlin Flow:测试挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61772409/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com