Lukasz Kalnik
04/13/2022, 12:51 PMviewModelScope
to collect an endless Flow in my viewModel
. In my unit test I want to "destroy" the ViewModel in order for viewModelScope
to cancel the Flow collection. I'm calling viewModel.onCleared()
but it doesn't cancel the `viewModelScope`'s children jobs.
How can I make sure all coroutines started inside viewModelScope
are canceled before my test ends, so runTest
doesn't hang waiting for the coroutines to finish?Javier
04/13/2022, 1:00 PMJavier
04/13/2022, 1:00 PMLukasz Kalnik
04/13/2022, 1:02 PMLukasz Kalnik
04/13/2022, 1:02 PMLukasz Kalnik
04/13/2022, 1:08 PMclass MyViewModel(coroutineContext: CoroutineContext = Dispatchers.Default) : ViewModel() {
private val coroutineScope = viewModelScope + coroutineContext
init {
coroutineScope.launch { myFlow.collect { /* do something with collected items */ } }
}
}
class MyViewModelTest {
@Test
fun testInitMyViewModel() = runTest {
MyViewModel(coroutineContext) // coroutineContext from test injected here
// test hangs and times out eventually because myFlow collection is not canceled
}
}
Javier
04/13/2022, 1:18 PMLukasz Kalnik
04/13/2022, 1:25 PMLukasz Kalnik
04/13/2022, 1:25 PMLukasz Kalnik
04/13/2022, 1:26 PMmyFlow
is not even accessible inside the test, because it comes from a dependencyLukasz Kalnik
04/13/2022, 1:27 PMLukasz Kalnik
04/13/2022, 1:28 PMLukasz Kalnik
04/13/2022, 1:28 PMUmar Ata
04/13/2022, 2:32 PMLukasz Kalnik
04/13/2022, 2:36 PMLukasz Kalnik
04/13/2022, 2:36 PMviewModelScope
Lukasz Kalnik
04/13/2022, 2:38 PMviewModelScope
, to cancel all children jobs when the ViewModel is destroyed. The only problem is that apparently a ViewModel cannot be destroyed from a unit test.Lukasz Kalnik
04/13/2022, 2:38 PMIan Lake
04/13/2022, 4:14 PMViewModelStore
via the ViewModelProvider
APIs to actually scope it to something. It is ViewModelStore
that has the clear()
method that cancels and clears every ViewModel added to itLukasz Kalnik
04/13/2022, 5:01 PMby viewModels(factoryProducer = {})
helper function to create a ViewModel tied to the Fragment's scope.
My question concerned however how to do it from a unit test.
Is there a possibility to also use a ViewModelStore
inside a unit test to call clear()
at the end of the test to cancel all children jobs of the viewModelScope
?Ian Lake
04/13/2022, 5:15 PMViewModelProvider
is just a regular class you can use in your test, etc.Lukasz Kalnik
04/13/2022, 5:24 PM