Recently, the class StateFlow was introduced as part of Kotlin coroutines.
I'm currently trying it and encountered an issue while trying to unit test my ViewModel. What I want to achieve: testing that my StateFlow is receiving all the state values in the correct order in my ViewModel.
My code is as follows.
ViewModel:
class WalletViewModel(private val getUserWallets: GetUersWallets) : ViewModel() {
val userWallet: StateFlow<State<UserWallets>> get() = _userWallets
private val _userWallets: MutableStateFlow<State<UserWallets>> =
        MutableStateFlow(State.Init)
fun getUserWallets() {
    viewModelScope.launch {
        getUserWallets.getUserWallets()
            .onStart { _userWallets.value = State.Loading }
            .collect { _userWallets.value = it }
    }
}
My test:
@Test
fun `observe user wallets ok`() = runBlockingTest {
    Mockito.`when`(api.getAssetWallets()).thenReturn(TestUtils.getAssetsWalletResponseOk())
    Mockito.`when`(api.getFiatWallets()).thenReturn(TestUtils.getFiatWalletResponseOk())
    viewModel.getUserWallets()
        
    val res = arrayListOf<State<UserWallets>>()
    viewModel.userWallet.toList(res) //doesn't works
    Assertions.assertThat(viewModel.userWallet.value is State.Success).isTrue() //works, last value enmited
}
Accessing the last value emitted works. But what I want to test is that all the emitted values are emitted in the correct order.
With this piece of code: viewModel.userWallet.toList(res) I'm getting the following error:
java.lang.IllegalStateException: This job has not completed yet
    at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1189)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
    at WalletViewModelTest.observe user wallets ok(WalletViewModelTest.kt:52)
....
I guess I'm missing something obvious. But not sure why as I'm just getting started with coroutines and Flow and this error seems to happen when not using runBlockingTest, which I use already.
EDIT:
As a temporary solution, I'm testing it as a live data:
@Captor
lateinit var captor: ArgumentCaptor<State<UserWallets>>
    
@Mock
lateinit var walletsObserver: Observer<State<UserWallets>>
@Test
fun `observe user wallets ok`() = runBlockingTest {
    viewModel.userWallet.asLiveData().observeForever(walletsObserver)
    
    viewModel.getUserWallets()
    captor.run {
        Mockito.verify(walletsObserver, Mockito.times(3)).onChanged(capture())
        Assertions.assertThat(allValues[0] is State.Init).isTrue()
        Assertions.assertThat(allValues[1] is State.Loading).isTrue()
        Assertions.assertThat(allValues[2] is State.Success).isTrue()
    }
}
 
     
     
     
     
    

 
     
     
     
    