You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:14:56