admin管理员组

文章数量:1122832

I want to write connected android tests which validate GUI behaviors and the navigations that are triggered. For example swiping on one screen to open a menu, which is a navigate() call to go to another screen.

Formerly I was using the mockk library to mock the NavHostController, but when I updated to a more recent version of Kotlin (2), mockk and Jetpack Compose, this no longer worked.

The Android documentation indicates that one should use the TestNavHostController, but in practice this has not worked for me.

Pertinent library versions:

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

If I try using the mockk:

    @MockK
    lateinit var navHostController: NavHostController


    @Before
    fun setupTest() {
        navHostController = mockk<NavHostController>(relaxed = true)
    }

    @Test
    fun `test with navhost`() {
        composeTestRule.setContent {
            MyLog(navHostController = navHostController, viewModel = myViewModel)
        }
    }

Then I get an error that I can't instantiate a proxy for the class NavHostController:

com.example.display.presentationponents.MyLogTest > tapping a card calls onInitiate[Wear_OS_Large_Round_API_34(AVD) - 14] FAILED 
        io.mockk.MockKException: Can't instantiate proxy for class androidx.navigation.NavHostController
        at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:64)

And if I try using TestNavHostController:

        val navHostController = TestNavHostController(
            ApplicationProvider.getApplicationContext(),
        )
        navHostController.createGraph(startDestination = Screen.MainScreen) {
            composable(Screen.MainScreen.route) {
                MainScreen(navHostController = navHostController)
            }
            composable(Screen.MainMenu.route) {
                MainMenu(navHostController)
            }
        }
        composeTestRule.setContent {
            navHostController.navigatorProvider.addNavigator(ComposeNavigator())
            MainScreen(myViewModel, navHostController)
        }
        mainscreen.performTouchInput { swipeLeft(startX = 300f, endX = 100f) }
        assertEquals(Screen.MainMenu.route, navHostController.currentDestination?.route)

I get an error that TestNavigatorProvider cannot be cast to WearNavigator:

com.example.display.presentationponents.MainScreenTest > when user swipes left it opens the main menu[Wear_OS_Large_Round_API_34(AVD) - 14] FAILED 
        java.lang.ClassCastException: androidx.navigation.testing.TestNavigatorProvider$navigator$1 cannot be cast to androidx.wearpose.navigation.WearNavigator
        at androidx.wearpose.navigation.NavGraphBuilderKtposable(NavGraphBuilder.kt:55)

本文标签: androidHow to test navigation when using Jetpack Compose on WearOSStack Overflow