如何测试含ViewModel与Hilt的Jetpack Compose导航?
测试Jetpack Compose导航逻辑(含Hilt ViewModel)
针对你提到的场景——验证首页按钮点击跳转到信息页,结合Hilt注入ViewModel的情况,以下是具体的测试方案:
1. 添加必要测试依赖
在Module级别的build.gradle中添加Compose测试、导航测试及Hilt测试相关依赖:
dependencies { // Compose UI测试 androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.5.4" debugImplementation "androidx.compose.ui:ui-test-manifest:1.5.4" // Navigation测试 androidTestImplementation "androidx.navigation:navigation-testing:2.7.5" // Hilt测试 androidTestImplementation "com.google.dagger:hilt-android-testing:2.48" kaptAndroidTest "com.google.dagger:hilt-android-compiler:2.48" }
2. 核心测试思路
测试导航的关键是用TestNavHostController替代真实的NavController,以此监听并验证导航动作;同时通过Hilt的测试注解提供ViewModel的依赖(或模拟依赖),保证测试的隔离性。
3. 编写导航测试用例
假设你的HomeScreen中有一个按钮,点击后调用navController.navigate(Screen.Info.route),以下是对应的测试代码:
3.1 配置Hilt测试环境
创建测试类并添加Hilt相关注解:
@HiltAndroidTest class HomeScreenNavigationTest { @get:Rule val hiltRule = HiltAndroidRule(this) @get:Rule val composeTestRule = createAndroidComposeRule<ComponentActivity>() private lateinit var testNavController: TestNavHostController @Before fun setUp() { hiltRule.inject() // 初始化TestNavHostController testNavController = TestNavHostController(composeTestRule.activity) // 设置导航图的起始目的地 testNavController.setGraph(R.navigation.your_nav_graph) // 替换为你的导航图资源ID } }
3.2 验证首页到信息页的跳转
添加测试方法,模拟按钮点击并验证导航:
@Test fun homeScreen_buttonClick_navigatesToInfoScreen() { // 启动HomeScreen,传入TestNavHostController和依赖的ViewModel composeTestRule.setContent { val homeViewModel = hiltViewModel<HomeViewModel>() val themeViewModel = hiltViewModel<ThemeViewModel>() val commonViewModel = hiltViewModel<CommonViewModel>() HomeScreen( navController = testNavController, themeViewModel = themeViewModel, viewModel = homeViewModel, commonViewModel = commonViewModel ) } // 模拟点击首页的跳转按钮(替换为你的按钮语义标签/文本) composeTestRule.onNodeWithContentDescription("跳转到信息页").performClick() // 验证导航到了InfoScreen的路由 assertEquals(Screen.Info.route, testNavController.currentBackStackEntry?.destination?.route) }
4. 模拟ViewModel的依赖(可选)
如果你的ViewModel依赖仓库,为了测试隔离,可以用Hilt的@BindValue模拟仓库实例:
@BindValue @JvmField val mockRepository: YourHomeRepository = mockk() // 使用MockK或Mockito创建模拟对象 @Before fun setUp() { hiltRule.inject() // 配置mock的行为 every { mockRepository.fetchData() } returns Result.success(emptyList()) }
5. 针对完整NavGraph的测试(可选)
如果你想测试整个NavGraph的导航流程,建议先重构NavGraph,允许外部传入navController(替代内部的rememberNavController()),然后编写测试:
@Test fun navGraph_homeToInfoNavigation() { composeTestRule.setContent { val themeViewModel = hiltViewModel<ThemeViewModel>() // 传入TestNavHostController NavGraph( themeViewModel = themeViewModel, navController = testNavController ) } // 点击首页按钮 composeTestRule.onNodeWithContentDescription("跳转到信息页").performClick() // 验证路由 assertEquals(Screen.Info.route, testNavController.currentDestination?.route) }
内容的提问来源于stack exchange,提问作者deja
相关产品推荐
相关产品推荐

