使用 Dispatchers.IO 进行 Kotlin 协程测试

Adr*_*zin 13 android unit-testing kotlin kotlin-coroutines

所以也许有一个教程来讨论这个问题,但是我读过的教程都没有为我解决这个问题。我有如下结构,正在尝试进行单元测试,但是当我去测试时,我总是失败,说明doSomthing()从未调用过 repo 方法。我最好的猜测是因为我在不同的上下文中启动了一个新的协程。那我该如何测试呢?

存储库

interface Repository {
    suspend fun doSomething(): String
}
Run Code Online (Sandbox Code Playgroud)

查看模型

class ViewModel(val repo: Repository) {
    val liveData = MutableLiveData<String>()
    fun doSomething {
    //Do something here
        viewModelScope.launch(Dispatchers.IO) {
            val data = repo.doSomething()
            withContext(Dispatchers.Main) {
                liveData.value = data
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

查看模型测试

class ViewModelTest {
    lateinit var viewModel: ViewModel
    lateinit var repo: Repository

    @Before
    fun setup() {
        Dispatchers.setMain(TestCoroutineDispatcher())
        repo = mock<Repository>()
        viewModel = ViewModel(repo)
    }

    @Test
    fun doSomething() = runBlockingTest {
        viewModel.doSomething()
        viewModel.liveData.test().awaitValue().assertValue {
            // assert something
        }
        verify(repo).doSomthing()
    }
}
Run Code Online (Sandbox Code Playgroud)

Emm*_*uel 21

根据谷歌的说法: 在此处输入图片说明

Dispatchers应该注入您的,ViewModels以便您可以正确测试。您正在设置TestCorotutineDispatcher为通过主调度Dispatchers.setMain这需要控制的MainDispatcher,但你仍然有超过经推出协同程序的执行没有控制viewModelScope.launch(Dispatchers.IO)

传递Dispatchervia 构造函数将确保您的测试和生产代码使用相同的调度程序。

通常@Rule定义为:

  1. 覆盖 MainDispatcher 通过Dispatchers.setMain(就像你正在做的那样)
  2. 使用TestCoroutineDispatcher's自己的runBlockingTest()来实际运行测试。

是去年 Android 开发者峰会上发生的关于测试和协程的非常好的演讲。

这里就是这样的一个例子@Rule。(无耻的插件。在那个 repo 上也有协程测试的例子)