首页 > 解决方案 > LiveData postValue 的 Mockito verify() 失败

问题描述

我创建了一个 LoginFragment,当使用导航架构组件成功登录时,它会导航到另一个。工作正常,但测试失败。它是 GithubBrowser 示例的非常接近的镜像,我的测试与此处clickRepo的测试非常相似,除了我正在测试当成功发布资源而不是单击时加载新页面。

错误:

Wanted but not invoked:
navController.navigate(
app.ui.login.LoginFragmentDirections$ShowSelectMerchant@377f3c27
);

登录片段测试.kt

@Test
fun success(){
    val user = TestUtil.createUser(email)

    userData.postValue(Resource.success(user))

    System.out.println("Test NavController Hash: " + testFragment.navController.hashCode())
            verify(testFragment.navController).navigate(LoginFragmentDirections.showSelectMerchant().matcher())

}

登录片段.kt

override fun openSelectMerchantFragment() {
    System.out.println("Real NavController Hash: " + navController().hashCode())
    navController().navigate(LoginFragmentDirections.showSelectMerchant())
}

openSelectMerchantFragment当成功的资源发布到实时用户数据时调用。测试失败是否有明显的原因?

我可以看到测试片段的模拟导航控制器和片段本身中调用的导航控制器具有相同的哈希值,所以我很确定这不是我如何模拟活动、片段或导航控制器的问题。我也可以清楚地看到,navigate() 函数肯定被调用了。

标签: androidmockitoandroid-testingandroid-architecture-navigation

解决方案


这里的问题是 Ian 建议的测试 LiveData 的一个简单问题。添加 是不够的TaskExecutorWithIdlingResourceRule,但drainTasks()必须调用才能完成数据发布。我无法回答为什么它在没有任何调用的情况下在样本的整个测试类中工作drainTasks,我最好的猜测是这些测试中的发布完成得足够快,不会成为问题。我认为drainTasks每当发布实时数据时始终调用是一种好习惯。

最后结果:

@Test
fun success(){
    val user = TestUtil.createUser(email)

    userData.postValue(Resource.success(user))
    executorRule.drainTasks(1, TimeUnit.SECONDS)

    verify(testFragment.navController).navigate(LoginFragmentDirections.showSelectMerchant().matcher())
}

推荐阅读