How to assert a LiveData that change the value two or more times after calling the function under test?

97 views Asked by At

when viewmodel init, if user is already logged in, the livedata _resultEvent.value will change twice

class LoginViewModel @Inject constructor( private val loginUseCase: LoginUser, private val getUserIfLogged: GetUserIfLogged ): ViewModel() {

private val _resultEvent = MutableLiveData<Event<AuthEvents<String>>>()
val resultEvent: LiveData<Event<AuthEvents<String>>> = _resultEvent

init {
    viewModelScope.launch {
        val userID = getUserIfLogged.invoke()
        if (userID != null){
            _resultEvent.value =
                Event(AuthEvents.SuccessSnackBar(message = "Welcome"))
            delay(1500)
            _resultEvent.value =
                Event(AuthEvents.NavigateToMainAuthenticated(userID))
        }
    }
    // other things....
}

when i write a test for this using the LiveDataTestUtil function by Google to observe livedata, i got a lot of errors

java.util.concurrent.TimeoutException: LiveData value was never set.

so i write a test that "works", but i am not sure that is the right way to do this kind of test using advanceTimeBy(), because if i don't know when the live data will change his value, or how much values will be emitted, i will not be able to do the test using this method.

// 
@Before fun setUp(){ 
Dispatchers.setMain(dispatcher) // StandardTestDispatcher() 
coEvery { getUserIfLogged.invoke() } returns null 
viewModel = LoginViewModel(loginUser, getUserIfLogged) 
}

@After 
fun tearDown(){ 
Dispatchers.resetMain() 
}

@Test fun if user is logged, init should emit a SnackBar and Navigate events() = runTest{ 

// Given 
coEvery { getUserIfLogged.invoke() } returns "someUserID"

// When (viewModel starts)
advanceTimeBy(1)
val result1 = viewModel.resultEvent.getOrAwaitValue()
advanceUntilIdle()
val result2 = viewModel.resultEvent.getOrAwaitValue()

// Then
coVerify { getUserIfLogged.invoke() }
assertTrue(result1?.getIfIsNotHandled() is AuthEvents.SuccessSnackBar)
assertTrue(result2?.getIfIsNotHandled() is AuthEvents.NavigateToMainAuthenticated)

}

please give me a feedback, is this test OK? or there are another better ways?

0

There are 0 answers