フローを収集する私のViewModelのメソッドをテストしたいです。コレクターの内側では、LiveDataオブジェクトが変わっています。これは最後にチェックしたいです。これはおおよそ設定の外観です。
_//Outside viewmodel
val f = flow { emit("Test") }.flowOn(Dispatchers.IO)
//Inside viewmodel
val liveData = MutableLiveData<String>()
fun action() {
viewModelScope.launch { privateAction() }
}
suspend fun privateAction() {
f.collect {
liveData.value = it
}
}
_
My Unit Testでaction()
メソッドを呼び出すと、フローが収集される前にテストが終了します。これがテストの外観の外観です。
_@Test
fun example() = runBlockingTest {
viewModel.action()
assertEquals(viewModel.liveData.value, "Test")
}
_
このJUNIT5拡張子を介してTestCoroutIneSpatcherを使用しています。また、LiveDataのInstant Executor拡張機能も使用しています。
_ class TestCoroutineDispatcherExtension : BeforeEachCallback, AfterEachCallback, ParameterResolver {
@SuppressLint("NewApi") // Only used in unit tests
override fun supportsParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Boolean {
return parameterContext?.parameter?.type === testDispatcher.javaClass
}
override fun resolveParameter(parameterContext: ParameterContext?, extensionContext: ExtensionContext?): Any {
return testDispatcher
}
private val testDispatcher = TestCoroutineDispatcher()
override fun beforeEach(context: ExtensionContext?) {
Dispatchers.setMain(testDispatcher)
}
override fun afterEach(context: ExtensionContext?) {
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
}
class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance()
.setDelegate(object : TaskExecutor() {
override fun executeOnDiskIO(runnable: Runnable) = runnable.run()
override fun postToMainThread(runnable: Runnable) = runnable.run()
override fun isMainThread(): Boolean = true
})
}
override fun afterEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance().setDelegate(null)
}
}
_
それで私が終わったことは、ディスパッチャーをViewModelコンストラクタに渡すだけです。
_class MyViewModel(..., private val dispatcher = Dispatchers.Main)
_
そして次のように使ってください:
_viewModelScope.launch(dispatcher) {}
_
だから私はViewModel
を使用してTestCoroutineDispatcher
をインスタンス化してから、_testCoroutineDispatcher.runBlockingTest {}
_などを使用して、これをオーバーライドできます。