測試 Compose 導覽功能

將導覽程式碼與可組合目的地分離,以便分別測試每個可組合項,與 NavHost 可組合項分開。

請勿將 NavController 直接傳遞給任何可組合函式。請改為將導覽回呼 (lambda) 做為參數傳遞。這樣一來,您的所有可組合項都能獨立測試,因為這類測試不需要 NavController 的執行個體。

NavHost 中的 composable lambda 可做為 Navigation API 與可組合項之間的橋樑:

@Composable
fun ProfileScreen(
    userId: String,
    navigateToFriendProfile: (friendUserId: String) -> Unit
) {
 // …
}

// In your NavHost
composable<Profile> { backStackEntry ->
    val profile = backStackEntry.toRoute<Profile>()
    ProfileScreen(userId = profile.id) { friendUserId ->
        navController.navigate(route = Profile(id = friendUserId))
    }
}

這樣一來,您就能傳遞模擬值和回呼,獨立測試 ProfileScreen,不必使用 Navigation。

建議您編寫涵蓋應用程式導覽要求的測試,測試 NavHost 時,導覽動作會傳遞至可組合項及個別畫面的可組合項。

測試 NavHost

如要開始測試 NavHost,請在應用程式模組的 build.gradle 檔案中新增下列導覽測試依附元件:

dependencies {
  androidTestImplementation "androidx.navigation:navigation-testing:$navigationVersion"
}

將應用程式的 NavHost 包裝在可組合函式中,該函式會接受 NavHostController 做為參數:

@Composable
fun AppNavHost(navController: NavHostController){
  NavHost(navController = navController, startDestination = Home){
      composable<Home> { /*...*/ }
      composable<Profile> { /*...*/ }
  }
}

現在,您可以傳遞導覽測試構件 TestNavHostController 的執行個體,測試 AppNavHostNavHost 內定義的導覽邏輯。

用於驗證應用程式起始目的地和 NavHost 的 UI 測試如下所示:

class NavigationTest {

    @get:Rule
    val composeTestRule = createComposeRule()
    lateinit var navController: TestNavHostController

    @Before
    fun setupAppNavHost() {
        composeTestRule.setContent {
            navController = TestNavHostController(LocalContext.current)
            navController.navigatorProvider.addNavigator(ComposeNavigator())
            AppNavHost(navController = navController)
        }
    }

    @Test
    fun appNavHost_verifyStartDestination() {
        composeTestRule
            .onNodeWithContentDescription("Start Screen")
            .assertIsDisplayed()
    }
}

測試導覽動作

您可以透過多種方式來測試導覽的實作情形,具體方法如下:點按 UI 元素,然後驗證顯示的目的地,或比較預期路徑和目前路徑。

如要測試導入應用程式,建議您按一下使用者介面。如要瞭解如何獨立測試個別可組合函式,請參閱「在 Jetpack Compose 中進行測試」程式碼研究室。

您也可以使用 navControllercurrentBackStackEntry,比較目前路徑與預期路徑,藉此檢查導覽斷言:

@Test
fun appNavHost_clickProfile_navigatesToProfile() {
    composeTestRule.onNodeWithContentDescription("Go to Profile")
        .performClick()

    assertTrue(navController.currentBackStackEntry?.destination?.hasRoute<Profile>() ?: false)
}

如要進一步瞭解 Compose 的測試基本概念,請參閱「測試 Compose 版面配置」指南。