Cómo probar la navegación de Compose

Separa el código de Navigation de los destinos componibles para habilitar la prueba de cada elemento componible de forma independiente del elemento componible NavHost.

No pases NavController directamente a ningún elemento componible. En su lugar, pasa devoluciones de llamada de navegación (lambdas) como parámetros. De esta manera, todos tus elementos componibles se pueden probar de forma individual, ya que no requieren una instancia de NavController en las pruebas.

La expresión lambda composable en tu NavHost actúa como un puente entre las APIs de Navigation y tu elemento componible:

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

De esta manera, ProfileScreen se puede probar de forma independiente de Navigation pasando valores y devoluciones de llamada simulados.

Se recomienda escribir pruebas que cubran los requisitos de navegación de la app con pruebas en NavHost, acciones de navegación que se pasan a los elementos componibles, así como a los elementos individuales de la pantalla.

Prueba el elemento NavHost

Para comenzar a probar tu NavHost, agrega la siguiente dependencia de navegación-prueba al archivo build.gradle del módulo de tu app:

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

Une el NavHost de tu app en un elemento componible que acepte un NavHostController como parámetro:

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

Ahora puedes probar AppNavHost y la lógica de navegación definida dentro de NavHost pasando una instancia del artefacto de prueba de navegación TestNavHostController.

Una prueba de la IU que verifique el destino de inicio de tu app y NavHost tendría el siguiente aspecto:

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

Prueba las acciones de navegación

Puedes probar tu implementación de navegación de varias maneras. Para ello, haz clic en los elementos de la IU y, luego, verifica el destino que se muestra o compara la ruta esperada con la ruta real.

Como deseas probar la implementación concreta de tu app, es preferible que hagas clic en la IU. Para aprender a probar esto junto con las funciones individuales de componibilidad por separado, consulta el codelab Pruebas en Jetpack Compose.

También puedes usar navController para verificar las aserciones de navegación comparando la ruta actual con la esperada, mediante el currentBackStackEntry:

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

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

Para obtener más información sobre los conceptos básicos de las pruebas de Compose, consulta la guía Cómo probar tu diseño de Compose.