Testare la navigazione di Compose

Disaccoppia il codice di navigazione dalle destinazioni componibili per consentire il test di ogni componente componibile in modo isolato, separato dal componente componibile NavHost.

Non passare NavController direttamente in nessun composable. Passa invece i callback di navigazione (lambda) come parametri. In questo modo, tutti i tuoi composable possono essere testati singolarmente, in quanto non richiedono un'istanza di NavController nei test.

La lambda composable in NavHost funge da ponte tra le API Navigation e il tuo 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))
    }
}

In questo modo, ProfileScreen può essere testato indipendentemente dalla navigazione passando valori e callback simulati.

Ti consigliamo di scrivere test che coprano i requisiti di navigazione dell'app testando NavHost, le azioni di navigazione trasmesse ai composable e i singoli composable delle schermate.

Testa NavHost

Per iniziare a testare NavHost, aggiungi la seguente dipendenza per i test di navigazione al file build.gradle del modulo dell'app:

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

Inserisci NavHost della tua app in un componente componibile che accetta un NavHostController come parametro:

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

Ora puoi testare AppNavHost e la logica di navigazione definita all'interno di NavHost passando un'istanza dell'artefatto di test di navigazione TestNavHostController.

Un test dell'interfaccia utente che verifica la destinazione iniziale della tua app e NavHost avrebbe questo aspetto:

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()
    }
}

Testare le azioni di navigazione

Puoi testare l'implementazione della navigazione in diversi modi, facendo clic sugli elementi dell'interfaccia utente e verificando la destinazione visualizzata o confrontando il percorso previsto con il percorso attuale.

Poiché vuoi testare l'implementazione della tua app concreta, sono preferibili i clic sull'interfaccia utente. Per scoprire come testare questo elemento insieme alle singole funzioni componibili in isolamento, consulta il codelab Test in Jetpack Compose.

Puoi anche utilizzare navController per controllare le asserzioni di navigazione confrontando la route corrente con quella prevista, utilizzando currentBackStackEntry:

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

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

Per ulteriori indicazioni sulle nozioni di base dei test di Compose, consulta la guida Testare il layout di Compose.