I'm trying to test this ViewModel with savedStateHandle
class PostListViewModel @ViewModelInject constructor(
private val coroutineScope: CoroutineScope,
private val getPostsUseCase: GetPostListUseCaseFlow,
@Assisted savedStateHandle: SavedStateHandle
) : AbstractPostListVM() {
private val _goToDetailScreen =
savedStateHandle.getLiveData<Event<Post>>(POST_DETAIL)
// MutableLiveData<Event<Post>>()
override val goToDetailScreen: LiveData<Event<Post>>
get() = _goToDetailScreen
private val _postViewState =
savedStateHandle.getLiveData<ViewState<List<Post>>>(POST_LIST)
// MutableLiveData<ViewState<List<Post>>>()
override val postViewState: LiveData<ViewState<List<Post>>>
get() = _postViewState
override fun getPosts() {
getPostsUseCase.getPostFlowOfflineFirst()
.convertToFlowViewState()
.onStart {
_postViewState.value = ViewState(status = Status.LOADING)
}
.onEach {
_postViewState.value = it
}
.launchIn(coroutineScope)
}
override fun refreshPosts() {
getPostsUseCase.getPostFlowOfflineLast()
.convertToFlowViewState()
.onStart {
_postViewState.value = ViewState(status = Status.LOADING)
}
.onEach {
_postViewState.value = it
}
.launchIn(coroutineScope)
}
override fun onClick(post: Post) {
_goToDetailScreen.value = Event(post)
}
}
And the test being
@Test
fun `given exception returned from useCase, should have ViewState ERROR offlineFirst`() =
testCoroutineRule.runBlockingTest {
// GIVEN
every {
savedStateHandle.getLiveData<ViewState<List<Post>>>(AbstractPostListVM.POST_LIST)
} returns MutableLiveData()
every {
savedStateHandle.getLiveData<Event<Post>>(AbstractPostListVM.POST_DETAIL)
} returns MutableLiveData()
every {
useCase.getPostFlowOfflineFirst()
} returns flow<List<Post>> {
emit(throw Exception("Network Exception"))
}
val testObserver = viewModel.postViewState.test()
// WHEN
viewModel.getPosts()
// THEN
testObserver
.assertValue { states ->
(states[0].status == Status.LOADING &&
states[1].status == Status.ERROR)
}
.dispose()
val finalState = testObserver.values()[1]
Truth.assertThat(finalState.error?.message).isEqualTo("Network Exception")
Truth.assertThat(finalState.error).isInstanceOf(Exception::class.java)
verify(atMost = 1) { useCase.getPostFlowOfflineFirst() }
}
This test works when i use MutableLiveData
instead of SavedStateHandle.getLiveData()
with this and other tests.
With savedStateHandle being mocked as
private val savedStateHandle: SavedStateHandle = mockk()
returns
io.mockk.MockKException: no answer found for: SavedStateHandle(#2).getLiveData(POST_LIST)
and i changed mocked savedStateHandle to with relaxed = true
private val savedStateHandle: SavedStateHandle = mockk(relaxed = true)
based on this question.
Now value of postViewState does not change and test fails with
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
What is the correct way to mock and get LiveData with SavedStateHandle
?