如何测试Android Jetpack Navigation中Fragment onCreate内的findNavController导航
解决方案
有官方原生支持的测试方案,要求使用 AndroidX Navigation 2.4.0及以上版本 + AndroidX Fragment 1.3.0及以上版本,适配子Fragment在onCreate阶段调用导航的场景。
实现原理
根据Navigation组件的更新逻辑,NavHostFragment会在所有子Fragment的onCreate执行前完成NavController的初始化。测试时我们只要将被测Fragment作为NavHostFragment的子页面加载,提前给NavHostFragment绑定预创建的TestNavHostController,即可在子Fragment的onCreate阶段正常获取到NavController实例。
完整测试代码示例
@RunWith(AndroidJUnit4::class) class TitleScreenTest { @Test fun testOnCreateTriggerNavigation() { // 1. 预创建TestNavHostController,配置导航图和初始目的地 val navController = TestNavHostController( ApplicationProvider.getApplicationContext() ).apply { setGraph(R.navigation.trivia) // 初始目的地设置为被测页面TitleScreen对应的ID setCurrentDestination(R.id.title_screen) } // 2. 创建绑定了测试NavController的NavHostFragment实例 val testNavHostFragment = NavHostFragment.create(R.navigation.trivia).apply { this.navController = navController } // 3. 启动NavHostFragment到测试容器,会自动加载初始目的地TitleScreen launchFragmentInContainer<NavHostFragment>( themeResId = R.style.Theme_MaterialComponents_DayNight_NoActionBar, factory = object : FragmentFactory() { override fun instantiate(classLoader: ClassLoader, className: String): Fragment { return if (className == NavHostFragment::class.java.name) { testNavHostFragment } else { super.instantiate(classLoader, className) } } } ) // 4. 直接验证导航结果是否符合预期 assertThat(navController.currentDestination?.id).isEqualTo(R.id.in_game) } }
依赖配置参考
确保测试依赖版本满足要求即可:
dependencies { def nav_version = "2.6.0" def fragment_version = "1.6.1" androidTestImplementation "androidx.navigation:navigation-testing:$nav_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
内容的提问来源于stack exchange,提问作者Victor Shpyrka
相关产品推荐
相关产品推荐

