Entkoppeln Sie den Navigationscode von Ihren komponierbaren Zielen, damit Sie jede komponierbare Funktion isoliert und unabhängig von der komponierbaren Funktion NavHost testen können.
Übergeben Sie NavController nicht direkt an eine Composable-Funktion. Übergeben Sie stattdessen Navigations-Callbacks (Lambdas) als Parameter. So können alle Ihre Composables einzeln getestet werden, da sie in Tests keine Instanz von NavController benötigen.
Die composable-Lambda-Funktion in Ihrem NavHost fungiert als Brücke zwischen den Navigation APIs und Ihrem Composable:
@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))
}
}
So kann ProfileScreen unabhängig von der Navigation getestet werden, indem Mock-Werte und ‑Callbacks übergeben werden.
Es wird empfohlen, Tests zu schreiben, die die Navigationsanforderungen Ihrer App abdecken. Testen Sie dazu NavHost, Navigationsaktionen, die an Ihre Composables übergeben werden, und Ihre einzelnen Screen-Composables.
NavHost testen
Wenn Sie mit dem Testen von NavHost beginnen möchten, fügen Sie der Datei build.gradle Ihres App-Moduls die folgende Abhängigkeit für Navigationstests hinzu:
dependencies {
androidTestImplementation "androidx.navigation:navigation-testing:$navigationVersion"
}
Schließen Sie das NavHost Ihrer App in eine zusammensetzbare Funktion ein, die ein NavHostController als Parameter akzeptiert:
@Composable
fun AppNavHost(navController: NavHostController){
NavHost(navController = navController, startDestination = Home){
composable<Home> { /*...*/ }
composable<Profile> { /*...*/ }
}
}
Sie können jetzt AppNavHost und die in NavHost definierte Navigationslogik testen, indem Sie eine Instanz des Navigationstestartefakts TestNavHostController übergeben.
Ein UI-Test, der das Startziel Ihrer App und NavHost überprüft, würde so aussehen:
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()
}
}
Navigationsaktionen testen
Sie können Ihre Navigationsimplementierung auf verschiedene Arten testen, indem Sie auf die UI-Elemente klicken und dann entweder das angezeigte Ziel überprüfen oder die erwartete Route mit der aktuellen Route vergleichen.
Da Sie die Implementierung Ihrer konkreten App testen möchten, sind Klicks auf die Benutzeroberfläche vorzuziehen. Informationen zum Testen von einzelnen zusammensetzbaren Funktionen finden Sie im Codelab Testing in Jetpack Compose.
Sie können auch navController verwenden, um Navigationsbehauptungen zu prüfen, indem Sie die aktuelle Route mit der erwarteten Route vergleichen. Verwenden Sie dazu currentBackStackEntry:
@Test
fun appNavHost_clickProfile_navigatesToProfile() {
composeTestRule.onNodeWithContentDescription("Go to Profile")
.performClick()
assertTrue(navController.currentBackStackEntry?.destination?.hasRoute<Profile>() ?: false)
}
Weitere Informationen zu den Grundlagen von Compose-Tests finden Sie im Leitfaden Compose-Layout testen.