挂起 60 秒后,runTest 中的测试 SharedFlow 失败并出现 UncompletedCoroutinesError

prf*_*low 5 testing kotlin kotlin-coroutines

我有一个类,它执行一些工作并立即在挂起函数内返回结果,但还包含一个公共 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
}
Run Code Online (Sandbox Code Playgroud)

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

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())
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能通过测试?

prf*_*low 4

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

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

testScope.backgroundScope当测试完成时将自动正确取消,并且测试将不再挂起并失败 UncompletedCoroutinesError。

资料来源: