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

WearOS中Jetpack Compose导航测试问题求助

解决Wear Compose导航测试的MockK失效与TestNavHostController类型转换问题

问题场景

在Wear Compose项目中编写UI测试,验证滑动打开菜单等操作触发的navigate()导航行为。升级Kotlin 2.0.21后,原使用MockK模拟NavHostController的方式失效;改用官方推荐的TestNavHostController时,出现TestNavigator无法转为WearNavigator的类型转换错误。

依赖版本

junit = "4.13.2"
kotlin = "2.0.21"
mockk = "1.13.13"
robolectric = "4.13"
navigation-compose = "2.8.4"

报错信息

MockK模拟时的报错

io.mockk.MockKException: Can't instantiate proxy for class androidx.navigation.NavHostController

TestNavHostController使用时的报错

java.lang.ClassCastException: androidx.navigation.testing.TestNavigatorProvider$navigator$1 cannot be cast to androidx.wear.compose.navigation.WearNavigator

解决方案

1. 问题根源解析

  • MockK失效:新版本NavHostController的构造逻辑与内部依赖更复杂,MockK无法直接代理该类,官方明确推荐使用TestNavHostController进行导航测试,而非模拟实现。
  • 类型转换错误:TestNavHostController默认注册通用TestNavigator,但Wear Compose导航依赖专属的WearNavigator,因此需要手动替换注册。

2. 正确初始化TestNavHostController

初始化时手动向navigatorProvider添加WearNavigator,覆盖默认的测试导航器:

import androidx.navigation.testing.TestNavHostController
import androidx.test.core.app.ApplicationProvider
import androidx.wear.compose.navigation.WearNavigator

// 测试类中初始化导航控制器
val navController = TestNavHostController(ApplicationProvider.getApplicationContext()).apply {
    navigatorProvider.addNavigator(WearNavigator())
    // 可选:绑定你的导航图
    setGraph(R.navigation.your_wear_nav_graph)
}

3. 完整测试示例

@RunWith(RobolectricTestRunner::class)
class WearMenuNavigationTest {

    private lateinit var navController: TestNavHostController
    private val composeTestRule = createComposeRule()

    @Before
    fun setup() {
        navController = TestNavHostController(ApplicationProvider.getApplicationContext()).apply {
            navigatorProvider.addNavigator(WearNavigator())
            setGraph(R.navigation.wear_main_nav)
        }
    }

    @Test
    fun swipeToOpenMenu_triggersNavigation() {
        // 加载测试UI
        composeTestRule.setContent {
            WearMainScreen(navController = navController)
        }

        // 模拟从屏幕边缘滑动打开菜单的操作
        composeTestRule.onRoot().performTouchInput {
            swipeLeft() // 根据实际UI布局调整滑动方向
        }

        // 验证导航目标是否正确
        assertEquals("menu_route", navController.currentDestination?.route)
    }
}

4. 额外注意事项

  • 确保项目使用Wear Compose专属导航API(如wearNavGraph、scalingLazyColumnComposable),而非通用Compose导航组件。
  • 若需验证导航参数,可通过navController.currentBackStackEntry?.arguments获取并校验。
  • 不建议强行用MockK模拟NavHostController,否则可能触发更多内部逻辑兼容性问题,优先遵循官方测试方案。

内容的提问来源于stack exchange,提问作者Jeremiah Jordan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:57:09