Handle LiveData Observer properly in ViewModel Testing

In MVVM, ViewModel exposes streams of events to which the Views can bind. Generally, we use LiveData inside ViewModel and the view can observe for live data changes.

When it comes to unit testing for ViewModel, we create an observer, passes that observer to Live data, and verify its changed event.

viewModel.sessionSubmitLiveData.observeForever(dataObserver)
viewModel.submitSession(submitRequest)
verify(dataObserver).onChanged(data)

You can explore this approach in the below article.

If we want to assert data, then how can we do that?

Photo by bruce mars on Unsplash

Let take an example, we make a simple API call, we show loading, then hide loading based on API event, then show data/error. So we have 3 states to represent. Thanks to Kotlin, we have sealed class

Loading, Error, Success

sealed class DataState<out T> {
data class Loading(val isLoading: Boolean) : DataState<Nothing()
data class Error(val error: Throwable) : DataState<Nothing>()
data class Success<T>(val data: T) : DataState<T>()
}

This is a simple ViewModel class that makes 1 API call, gets data from the server then updates live data. As soon as we trigger API call, we show loading, then we hide loading then we show data/error based on API status.

How to test the above scenario?

Create a mock observer & argumentCaptor with the same type as we used for LiveData in ViewModel.

ArgumentCaptor is used to capture argument values for further assertions.

val argCaptor = argumentCaptor<DataState<SubmitResponse>>()private val submitStateObserver by lazy {mock<Observer<DataState<SubmitResponse>>>() }

Pass this argumentCaptor to the observer to capture all value changes for live data. This will give all events values.

onChanged(argCaptor.capture())

Source Code :

Thanks for reading the article.

Android Engineer | OlaElectric | https://droiddevgeeks.github.io