Ktor 客户端单元测试在 CoroutineScope.launch() 内挂起/冻结
Ktor client unit test hangs / freezes within CoroutineScope.launch()
我的 KMM 项目在测试在新范围内异步启动的 ktor 客户端请求时遇到问题。出于测试目的,我将 Dispatchers.Unconfined
作为新范围的上下文传入(在实际生产代码中,我使用 newSingleThreadContext()
)。
我在下面创建了一个极其简化的挂起 ktor 请求版本:
@ExperimentalCoroutinesApi
@Test
fun testExample(): Unit {
val scope = CoroutineScope(Dispatchers.Unconfined)
scope.launch {
val client = HttpClient { BrowserUserAgent() }
// This line hangs
val response : HttpResponse = client.get("https://google.com")
// Will never get here
println("Response: $response")
fail("This test should fail")
}
}
请注意,如果您不在 CoroutineScope.launch 内调用,则它可以正常工作。然后挂起/冻结仅在 CoroutineScope.launch 内调用时发生。同样,这是一个极其简化的示例,但在我的实际代码中,以这种方式设置的原因是我可以在最终发出 ktor 请求之前在后台线程中处理一些数据——因此 CoroutineScope.launch。另请注意,当 运行 在 iOS 模拟器上时,我的代码似乎工作正常。 它仅在 运行 作为单元测试时挂起 。
我是不是遗漏了一些东西来完成这项工作,还是这是一个错误?
我的解决方案最终是 运行 我在 运行Blocking() 范围内的测试,并将其 coroutineContext
注入我的 class 以供使用当 运行宁 CoroutineScope.launch().
object RequestService {
private val requestContext = newSingleThreadContext("request")
var testContext by AtomicReference<CoroutineContext?>(null)
fun makeRequest(block : () -> Unit) {
CoroutineScope.launch(testContext ?: requestContext) {
block()
}
}
}
@Test
fun testExample() = runBlocking {
RequestService.testContext = this.coroutineContext
RequestService.makeRequest() {
println("Running Ktor coroutine test")
val client = HttpClient { BrowserUserAgent() }
// This line doesn't hang anymore when running within runBlocking coroutineContext
val response : HttpResponse = client.get("https://google.com")
println("Response: $response")
}
println("Finished running Ktor coroutine test")
}
希望这对其他试图创建跨平台可测试服务的人有所帮助。感谢 帮助我到达那里的评论。
我的 KMM 项目在测试在新范围内异步启动的 ktor 客户端请求时遇到问题。出于测试目的,我将 Dispatchers.Unconfined
作为新范围的上下文传入(在实际生产代码中,我使用 newSingleThreadContext()
)。
我在下面创建了一个极其简化的挂起 ktor 请求版本:
@ExperimentalCoroutinesApi
@Test
fun testExample(): Unit {
val scope = CoroutineScope(Dispatchers.Unconfined)
scope.launch {
val client = HttpClient { BrowserUserAgent() }
// This line hangs
val response : HttpResponse = client.get("https://google.com")
// Will never get here
println("Response: $response")
fail("This test should fail")
}
}
请注意,如果您不在 CoroutineScope.launch 内调用,则它可以正常工作。然后挂起/冻结仅在 CoroutineScope.launch 内调用时发生。同样,这是一个极其简化的示例,但在我的实际代码中,以这种方式设置的原因是我可以在最终发出 ktor 请求之前在后台线程中处理一些数据——因此 CoroutineScope.launch。另请注意,当 运行 在 iOS 模拟器上时,我的代码似乎工作正常。 它仅在 运行 作为单元测试时挂起 。
我是不是遗漏了一些东西来完成这项工作,还是这是一个错误?
我的解决方案最终是 运行 我在 运行Blocking() 范围内的测试,并将其 coroutineContext
注入我的 class 以供使用当 运行宁 CoroutineScope.launch().
object RequestService {
private val requestContext = newSingleThreadContext("request")
var testContext by AtomicReference<CoroutineContext?>(null)
fun makeRequest(block : () -> Unit) {
CoroutineScope.launch(testContext ?: requestContext) {
block()
}
}
}
@Test
fun testExample() = runBlocking {
RequestService.testContext = this.coroutineContext
RequestService.makeRequest() {
println("Running Ktor coroutine test")
val client = HttpClient { BrowserUserAgent() }
// This line doesn't hang anymore when running within runBlocking coroutineContext
val response : HttpResponse = client.get("https://google.com")
println("Response: $response")
}
println("Finished running Ktor coroutine test")
}
希望这对其他试图创建跨平台可测试服务的人有所帮助。感谢