I have a viewmodel class that uses a StateFlow that is created using the StateIn operator.
I.E.
private val _state = MutableStateFlow(MyState())
private val myItems = myRepository.myFlow.stateIn(
viewModelScope, SharingStarted.WhileSubscribed(), emptyList<MyObject>())
val state: StateFlow<MyState> = combine(_state, myItems ) { state, myItems ->
..///
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), MyState())
When reading the documentation and various articles and SO questions (which are outdated), I saw that you are supposed to test this by using:
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
//Collect your flow
}
The problem I am having is that when I create a unit test to test my viewmodel, the collection of the state is not fast enough for the assertions that take place.
@Test
fun checkMyItemTest() = runTest {
val results = mutableListOf<MyState>()
val job = backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.state.collect {
results.add(it)
}
}
viewModel.onEvent(MyEvent.DoSomething())
assert(results[0].myStateParameter) //Perform some check on results[0]
assert(results[1].myStateParameter) //Perform some check on results[1]
job.cancel()
}
The test above fails in the second assertion, since results has only one element in it.
I have gotten it to work by shoving a Thread.sleep call of 50ms between the two assert calls, but that does not seem like the best approach to me.
@Test
fun checkMyItemTest() = runTest {
val results = mutableListOf<MyState>()
val job = backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.state.collect {
results.add(it)
}
}
viewModel.onEvent(MyEvent.DoSomething())
assert(results[0].myStateParameter) //Perform some check on results[0]
Thread.sleep(50). /// <---- THIS
assert(results[1].myStateParameter) //Perform some check on results[1]
job.cancel()
}
I am not interested in using Turbine at the moment
So I am looking to understand how I can test my flow properly and how I can collect the values emitted by it.