Search code examples
androidkotlinkotlinx.coroutinesandroid-viewmodel

Android: ViewModel test using kotlin coroutines not working


I'm using coroutines for the first time and I'm having troubles testing my work on a ViewModel. The test fails with

Wanted but not invoked:
observer.onChanged(<Capturing argument>);

The test is the following:

val androidVersioningMock: Versioning.AndroidVersioning = mock {
    on { required } doAnswer { "3.3.6" }
}
val versioningMock: Versioning = mock {
    on { android } doAnswer { androidVersioningMock }
}
whenever(networkManager.getAppVersionAsync()).thenReturn(GlobalScope.async { versioningMock })
runBlocking {
    updateVersionModel =
        UpdateViewModel(application, coroutineDispatcherProvider).apply {
            updateLiveData.observeForever(stateObserver)
        }
    verify(stateObserver).onChanged(stateCaptor.capture())
    assertTrue(stateCaptor.lastValue is UpdateState.NoUpdate)
    assertEquals(UpdateState.NoUpdate, stateCaptor.lastValue)
}

I have mocked the coroutineDispatcherProvider with

@ExperimentalCoroutinesApi
override val coroutineDispatcherProvider = mock<CoroutineDispatcherProvider> {
    on { main } doAnswer { TestCoroutineContext() }
    on { io } doAnswer { TestCoroutineContext() }
}

And in my ViewModel, the method that fails is

private suspend fun getUpdateVersion(): Versioning =
    withContext(coroutineDispatcherProvider.io) {
        networkManager.getAppVersionAsync().await()
    }

which is executed like :

launch {
    val versioningModel = getUpdateVersion()
    ...
}

Am I not mocking something or not doing something? Thanks in advance!


Solution

  • The TestCoroutineContext dispatcher is useful to handle timing within tests, but you want to run asynchronous calls synchronously. You should be able to achieve this with the Unconfined dispatcher.