Espresso测试中TestNavHostController.setCurrentDestination设置异常问题
问题根源
setCurrentDestination调用时机错误:在给目标View绑定NavController之前就修改了控制器的当前目的地,Navigation组件绑定控制器时会自动重置目的地为导航图默认的startDestination,导致之前的修改失效。- 测试场景下使用的
TestNavHostController必须先完成和View的绑定,再修改目的地状态,修改结果才会被持久化。
你之前尝试的修改NavController获取方式的方案都不生效,是因为问题本质是NavController本身的状态错误,和获取方式无关。
修复方案
调整launchFragment方法的执行顺序,将setCurrentDestination的调用放到View绑定NavController之后执行,如果需要保留完整回退栈可配合NavDeepLinkBuilder使用。
修复后的核心代码
protected inline fun <reified A : AppCompatActivity, reified F : Fragment> launchFragment( @NavigationRes navigationResource: Int, @IdRes fragmentId: Int, fragmentArgs: Bundle? = null ) { launchFragmentInHiltContainer<A, F>(fragmentArgs = fragmentArgs) { // 初始化测试用导航控制器 val navController = TestNavHostController(ApplicationProvider.getApplicationContext()) // 先加载导航图,不自动触发起始页跳转 navController.setGraph(navigationResource, null) this.viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner -> viewLifecycleOwner ?: return@observeForever // 第一步:给当前Fragment的View绑定导航控制器 Navigation.setViewNavController(this.requireView(), navController) // 第二步:绑定完成后再切换到目标目的地 navController.setCurrentDestination(fragmentId, fragmentArgs) // 可选:如果需要和正常业务流一致的完整回退栈,替换上面的setCurrentDestination为以下代码 /* val backStack = NavDeepLinkBuilder(ApplicationProvider.getApplicationContext()) .setGraph(navigationResource) .setDestination(fragmentId) .setArguments(fragmentArgs) .createTaskStackBuilder() .intents.first() .extras navController.restoreState(backStack) */ } } }
验证点
- 确认传入的
fragmentId是导航图中声明的目的地ID,而非Fragment布局ID或容器ID - 测试中调用
findNavController().currentDestination即可返回设置的目标Fragment,跳转动作可正常匹配对应action
内容的提问来源于stack exchange,提问作者Quintin B
相关产品推荐
相关产品推荐

