首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MockK模拟视图模型的savedStateHandle.getLiveData()

MockK模拟视图模型的savedStateHandle.getLiveData()
EN

Stack Overflow用户
提问于 2020-08-28 00:42:07
回答 2查看 1K关注 0票数 2

我正在尝试用savedStateHandle测试这个ViewModel

代码语言:javascript
复制
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)
    }
}

测试是

代码语言:javascript
复制
@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()时,此测试可以正常工作。

savedStateHandle被嘲笑为

private val savedStateHandle: SavedStateHandle = mockk()

返回

代码语言:javascript
复制
io.mockk.MockKException: no answer found for: SavedStateHandle(#2).getLiveData(POST_LIST)

我将mocked savedStateHandle更改为with relaxed = true

代码语言:javascript
复制
private val savedStateHandle: SavedStateHandle = mockk(relaxed = true)

基于此question

现在postViewState的值不变,测试失败,返回

代码语言:javascript
复制
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

使用SavedStateHandle模拟和获取LiveData的正确方法是什么

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-26 14:55:14

我已经用MockK库找到了解决方案,它工作正常,

我已经通过下面的方式做到了

代码语言:javascript
复制
val savedStateHandle = mockk<SavedStateHandle>(relaxed = true)

在上面的代码行中,我创建了在ViewModel中使用的savedStateHandle

代码语言:javascript
复制
@Test
fun `test something simple`() {
    val savedStateHandle = mockk<SavedStateHandle>(relaxed = true)
    val viewModel = MyViewModel(savedStateHandle)
    verify { savedStateHandle.set(MyViewModel.KEY, "Something") }
}
票数 2
EN

Stack Overflow用户

发布于 2021-06-04 04:08:04

也许是因为我使用了junit5,所以选择的答案对我不起作用。

如果它对某人有帮助,我所做的是用我需要的信息创建一个SavedStateHandle实例,而不是在测试的第一部分(在给定/排列部分)模拟它,并在那之后初始化ViewModel:

代码语言:javascript
复制
@Test
fun `whatever`() =
    coroutineRule.testDispatcher.runBlockingTest {
        val savedStateHandle = SavedStateHandle().apply {
            set(MyViewModel.KEY, "something")
        }
        val viewModel = PostListViewModel(coroutineScope, getPostsUseCase, savedStateHandle)

        ...
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63620562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档