如何正确测试带延迟的无限协程循环

How to properly test infinite coroutine loop with delay

提问人:Miltos 提问时间:7/14/2021 更新时间:7/14/2021 访问量:751

问:

我有一个无限运行的协程函数,每 8 秒进行一次 API 调用。我正在尝试测试它,但感觉有些不对劲。代码如下:

class RefreshStocksUseCaseImpl(
    private val dispatcherProvider: DispatcherProvider,
    private val stocksRepository: StocksRepository
) : RefreshStocksUseCase {

    override suspend fun invoke() {
        withContext(dispatcherProvider.io) {
            try {
                while (true) {
                    stocksRepository.refreshStocks()
                    delay(THRESHOLD)
                }
            } catch (t: Throwable) {
                // We could make some extra handling here.
                throw t
            }
        }
    }

    companion object {

        private const val THRESHOLD = 8_000L // 8 seconds
    }
}

我的测试如下所示:

@ExperimentalCoroutinesApi
class RefreshStocksUseCaseImplTest {

    private lateinit var useCase: RefreshStocksUseCase

    private val dispatcherProvider = TestDispatcherProvider()

    @MockK
    private lateinit var stocksRepository: StocksRepository

    @Before
    fun setup() {
        MockKAnnotations.init(this, relaxUnitFun = false)
        useCase = RefreshStocksUseCaseImpl(dispatcherProvider, stocksRepository)
    }

    @Test
    fun `refreshStocks is called again after threshold`() = dispatcherProvider.io.runBlockingTest {
        coEvery { stocksRepository.refreshStocks() } just runs

        val job = launch {
            useCase()
        }
        advanceTimeBy(8_000)

        job.cancel()
        coVerify(exactly = 2) { stocksRepository.refreshStocks() }
    }
}

即使它过去了,我也觉得我做错了什么。我觉得应该在这里扮演一些角色......欢迎任何改进。pauseDispatcher

Android While-Loop 延迟 Kotlin-coroutines

评论

0赞 Revolutionair 7/24/2023
我想知道你是否曾经改进过这段代码,以及你将如何使用新的测试 API(不使用已弃用的 )。我目前正在处理一个非常类似的情况,我的想法是像你一样编写测试,但我甚至无法使测试成功runBlockingTest
0赞 Miltos 7/25/2023
你能分享一个代码片段吗?您遇到的错误是什么?
0赞 Revolutionair 7/26/2023
我发现我的问题是在 viewModelScope 上启动的协程,因此取消它使测试按预期工作。不过谢谢你!

答: 暂无答案