You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kotlin Flow与Jetpack Compose的ViewModel单元测试实现问题

解决方案

你遇到的问题核心是调用searchCharacter后,函数内部启动的viewModelScope协程的Flow收集逻辑还未执行完成,就尝试读取result的值,因此拿到的还是初始空列表。按以下步骤改造即可:


第一步:前置优化(可选但推荐)

当前ViewModel持有Context并直接弹Toast不符合关注点分离原则,建议把错误提示逻辑移到UI层,ViewModel仅暴露错误事件即可,这样测试时不需要mock Context,可避免很多无关报错。如果你暂时不想改业务逻辑,需要先mock Toast的调用避免测试崩溃:
如果你用Mockito,需要在测试类加静态mock:

@Before
fun setup() {
    repository = FakeRepositoryImpl()
    //  mock Toast的静态方法
    mockStatic(Toast::class.java)
    `when`(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mock(Toast::class.java))
    viewModel = MarvelViewModel(repository)
}

第二步:改造测试逻辑

调用searchCharacter后,需要让测试调度器执行完所有待执行的协程任务,再进行断言:

@OptIn(ExperimentalCoroutinesApi::class)
class MarvelViewModelTest {

    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()

    @get:Rule
    var mainCoroutineRule = MainCoroutineRule()

    private val context = mock(Context::class.java)

    private lateinit var viewModel: MarvelViewModel
    private lateinit var repository: FakeRepositoryImpl

    @Before
    fun setup() {
        repository = FakeRepositoryImpl()
        mockStatic(Toast::class.java)
        `when`(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mock(Toast::class.java))
        viewModel = MarvelViewModel(repository)
    }

    @Test
    fun `searchCharacter should update result state when get response success`() = runTest {
        //  调用业务方法
        viewModel.searchCharacter("iron man", context)
        //  等待所有协程任务执行完成
        mainCoroutineRule.scheduler.advanceUntilIdle()
        //  断言结果符合预期
        assert(viewModel.result.value.size == 4)
        assert(viewModel.result.value.first().name == "Iron Man")
    }
}

注意事项

  • 如果你使用的是kotlinx-coroutines-test 1.6.0及以上版本,runBlockingTest已经废弃,替换为runTest即可,功能一致
  • advanceUntilIdle()会让测试协程调度器执行完所有排队的任务,确保Flow的所有发射、收集逻辑都执行完成,此时读取MutableState的value就是更新后的值

内容的提问来源于stack exchange,提问作者Henrique Tavolaro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 13:09:01