如何解决MockK模拟ViewModel的savedStateHandle.getLiveData
我正在尝试使用saveStateHandle测试此ViewModel
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)
}
}
测试正在进行
@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() }
}
当我在此测试和其他测试中使用MutableLiveData
而不是SavedStateHandle.getLiveData()
时,此测试有效。
将saveStateHandle模拟为
private val savedStateHandle: SavedStateHandle = mockk()
返回
io.mockk.MockKException: no answer found for: SavedStateHandle(#2).getLiveData(POST_LIST)
我用relaxed = true
更改了模拟的saveStateHandle
private val savedStateHandle: SavedStateHandle = mockk(relaxed = true)
基于此question。
postViewState的现在值不变,并且测试失败,
java.lang.IndexOutOfBoundsException: Index: 0,Size: 0
使用SavedStateHandle
模拟和获取LiveData的正确方法是什么?
解决方法
我找到了 MockK 库的解决方案,并且运行良好,
我已经按照以下方式完成了
val savedStateHandle = mockk<SavedStateHandle>(relaxed = true)
通过上面的行,我创建了在 ViewModel 中使用的 saveStateHandle
@Test
fun `test something simple`() {
val savedStateHandle = mockk<SavedStateHandle>(relaxed = true)
val viewModel = MyViewModel(savedStateHandle)
verify { savedStateHandle.set(MyViewModel.KEY,"Something") }
}
,
也许是因为我使用的是 junit5,所选的答案对我不起作用。
如果它对某人有帮助,我所做的是使用我需要的信息创建一个 SavedStateHandle
实例,而不是在测试的第一部分(在 Given/Arrange 部分)模拟它并初始化 ViewModel之后:
@Test
fun `whatever`() =
coroutineRule.testDispatcher.runBlockingTest {
val savedStateHandle = SavedStateHandle().apply {
set(MyViewModel.KEY,"something")
}
val viewModel = PostListViewModel(coroutineScope,getPostsUseCase,savedStateHandle)
...
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。