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?