我创建了一个LoginFragment,当使用导航架构组件成功登录时,它会导航到另一个LoginFragment。工作正常,但测试失败。它是 GithubBrowser 示例的非常接近的镜像,我的测试与这里的clickRepo
测试非常相似,除了我正在测试在发布成功的资源而不是单击时加载新页面。
错误:
Wanted but not invoked:
navController.navigate(
app.ui.login.LoginFragmentDirections$ShowSelectMerchant@377f3c27
);
LoginFragmentTest.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())
}
LoginFragment.kt
override fun openSelectMerchantFragment() {
System.out.println("Real NavController Hash: " + navController().hashCode())
navController().navigate(LoginFragmentDirections.showSelectMerchant())
}
当成功的资源发布到实时用户数据时,将调用openSelectMerchantFragment
。测试失败是否有明显的原因?
我可以看到测试片段的模拟导航控制器和片段本身中调用的控制器具有相同的哈希值,因此我很确定我模拟活动、片段或导航控制器的方式不是问题。我还清楚地看到 navigate(( 函数肯定被调用了。
这里的问题是像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())
}