kotlin 测试最新的API用法

ehxuflar  于 2023-01-05  发布在  Kotlin
关注(0)|答案(1)|浏览(97)

我正在用最近的协程测试API为ViewModel类编写一个测试用例,它没有按预期工作。

@Test
fun `when balanceOf() is called with existing parameter model state is updated with correct value`() = runTest {
    Dispatchers.setMain(StandardTestDispatcher())
    fakeWalletRepository.setPositiveBalanceOfResponse()
    assertThat("Model balance is not default", subj.uiState.value.wallet.getBalance().toInt() == 0)
    assertThat("Errors queue is not empty", subj.uiState.value.errors.isEmpty())
    assertThat("State is not default", subj.uiState.value.status == Status.NONE)

    subj.balanceOf("0x6f1d841afce211dAead45e6109895c20f8ee92f0")
    advanceUntilIdle()

    assertThat("Model balance is not updated with correct value", subj.uiState.value.wallet.getBalance().toLong() == 42L)
    assertThat("Errors queue is not empty", subj.uiState.value.errors.isEmpty())
    assertThat("State is not set as BALANCE", subj.uiState.value.status == Status.BALANCE)
}

该问题工作不稳定-通常会失败,在调试器下通常会通过。
根据我的理解,StandartTestDispatcher应该在UnconfinedTestDispatcher立即运行协程时,在advanceUntilIdle调用之前不运行协程。advanceUntilIdle应该等到所有协程都完成,但似乎在下一个assertThat()调用中存在争用条件,这会导致我的测试用例行为的模糊性。
advanceUntilIdle应该保证所有的协程结束它们的工作。这是否意味着在.collect{}state.update {}调用下的某个地方发生了竞态条件?(在我的理解中,advanceUntilIdle也应该等待它们的执行结束)
x一个一个一个一个x一个一个二个x

nxowjjhe

nxowjjhe1#

从我看到的余额()在IO调度程序上执行,您在viewModelScope中收集(这是主.立即调度器). IO调度器在你的测试中没有被覆盖,这就是导致你的测试不可预测的原因.因为目前没有办法像setMain那样覆盖IO调度器,您可以通过添加默认参数来添加覆盖ViewModel中后台调度程序的功能,例如:

ViewModel(private val backgroundDispatcher: CoroutineDispatcher = Dispatchers.IO)

并在代码中替换它:

fun balanceOf(owner: String) {
    logger.d("[start] balanceOf()")
    viewModelScope.launch {
        repository.balanceOf(owner)
            .flowOn(backgroundDispatcher)
            .collect { value ->
                logger.d("collect get balance result")
                processBalanceOfResponse(value)
            }
    }
    logger.d("[end] balanceOf()")
}

然后在测试中使用标准测试调度器示例化ViewModel,它应该可以工作。您可以查看此页以了解问题:https://developer.android.com/kotlin/coroutines/test#injecting-test-dispatchers

相关问题