android - MockK 模拟 ViewModel 的 savedStateHandle.getLiveData()

标签 android android-livedata android-viewmodel mockk

我正在尝试使用 savedStateHandle 测试这个 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()通过这个和其他测试。
将 savedStateHandle mock 为private val savedStateHandle: SavedStateHandle = mockk()返回
io.mockk.MockKException: no answer found for: SavedStateHandle(#2).getLiveData(POST_LIST)
我将模拟的 savedStateHandle 更改为 relaxed = true
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 中使用过的 savedStateHandle
@Test
fun `test something simple`() {
    val savedStateHandle = mockk<SavedStateHandle>(relaxed = true)
    val viewModel = MyViewModel(savedStateHandle)
    verify { savedStateHandle.set(MyViewModel.KEY, "Something") }
}

关于android - MockK 模拟 ViewModel 的 savedStateHandle.getLiveData(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63620562/

相关文章:

android - OpenStreetMap 上的空网格

android - 从联系人 ID : android 中检索电话号码

android - 将 LiveData<Resource<User>> 转换为 LiveData<User> 时的类型干扰问题

如果快速调用,android LiveData Observable 不会返回数据

android - 如果不是Rotation,请使用ViewModel

android - 如何在依赖于 View 模型的可组合函数中获得预览?

java - Android - Firebase OrderByChild 使应用程序崩溃

javascript - Cordova InAppBrowser 和 FaceBook 应用程序事件记录器

android - LiveData 和 MutableLiveData 的区别

android - 如何在 Kotlin 中传递方法接受参数?