【问题标题】:Testing SharedFlow in runTest fails with UncompletedCoroutinesError after hanging for 60 seconds挂起 60 秒后,在 runTest 中测试 SharedFlow 失败并出现 UncompletedCoroutinesError
【发布时间】:2022-12-23 00:20:13
【问题描述】:

我有一个执行一些工作并立即在挂起函数内返回结果的类,但还包含一个公共 SharedFlow 来更新其他组件有关此工作何时发生的信息(例如,一个执行用户登录然后还提供 Flow 的类在新用户登录时更新监听器:

class ExampleClass(private val api: Api, externalScope: CoroutineScope) {
    private val _dataFlow = MutableSharedFlow<String>()
    val dataFlow = _dataFlow.shareIn(externalScope, SharingStarted.Lazily)

    suspend fun performLogin(): String {
        val result = api.getData()
        _dataFlow.emit(result)
        return result
    }
}

interface Api {
    suspend fun getData(): String
}

我已经为这门课写了一个测试。测试中的断言通过了,但是和UncompletedCoroutinesError挂了60秒后还是失败了:

class ExampleClassTest {
    private val mockApi = mockk<Api> { coEvery { getData() } returns "hello" }
    private val testScope = TestScope()

    @Test
    fun thisTestTimesOutAndFails() = testScope.runTest {
        val exampleClass = ExampleClass(mockApi, testScope)
        assertEquals("hello", exampleClass.performLogin())
    }
}

我如何才能通过测试?

【问题讨论】:

    标签: kotlin testing kotlin-coroutines


    【解决方案1】:

    即使将 testScope.runTest 替换为顶级 runTest 可以使测试通过,重要的是要确保您的测试中只有一个 TestScope,否则可能会出现不良行为。要使用单个 TestScope 解决此问题,我们可以将其 backgroundScope 传递给被测类:

        @Test
        fun thisTestPasses() = testScope.runTest(dispatchTimeoutMs = 1000) {
            val exampleClass = ExampleClass(mockApi, testScope.backgroundScope)
            assertEquals("hello", exampleClass.performLogin())
        }
    

    testScope.backgroundScope会在测试结束时自动正确取消,测试不会再挂起失败UncompletedCoroutinesError。

    资料来源:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 2014-12-02
      • 2020-05-25
      • 1970-01-01
      相关资源
      最近更新 更多