How to Test the Navigation Component in Jetpack Compose?

Emine İNAN
Huawei Developers
Published in
6 min readMay 23, 2023
Photo by Javier Allegue Barros on Unsplash

Introduction 🌟

Testing is important for guaranteeing your code behaves as expected and for increasing the quality of your project by identifying errors early in the development process.

In this article, we will learn how to test the Navigation Component in Jetpack Compose. As a prerequisite, you need to be familiar with the Navigation component in Jetpack Compose. Let’s get started!

Test the Mood Tracker App

The Mood Tracker app has multiple screens to navigate through and a variety of actions that can be taken by the user.

Mood Tracker App

To start testing the Mood Tracker app, you can access the project’s starter code here.

The following diagram shows the navigational flow for the Mood Tracker app:

Routes

🚩 The Start Mood Tracker button on the Start Mood Tracker screen navigates to the Choose Mood screen.

🚩 The Submit button on the Choose Mood screen navigates to the Mood Checkout screen.

🚩 The Ok button on the Mood Checkout screen navigates to the Start Mood Tracker screen.

🚩 The Cancel button on the Choose Mood screen navigates to the Start Mood Tracker screen.

🚩 The Back button on any screen navigates back to the previous screen.

Now let’s write tests to verify these navigation states!

Step 1

Open the build.gradle(Module: app) file and add the following dependency to the dependencies section of the file:

build.gradle

Step 2

Create a new Kotlin class called MoodTrackerScreenNavigationTest in the test directory.

MoodTrackerScreenNavgationTest

Step 3

UI tests in Compose require a Compose test rule, so we need to write a Compose test rule to test Jetpack Navigation.

In MoodTrackerScreenNavigationTest class, create a test rule using createAndroidComposeRule and passing ComponentActivity as the type parameter.

MoodTrackerScreenNavgationTest

Step 4

To make sure that your app navigates to the correct place, create a TestNavHostController instance as a lateinit variable.

Create a function called setupMoodTrackerAppNavHost() with @Before annotation and call the setContent() function on the Compose test rule.

Set up the nav host and initialize the navController variable you created, register a navigator, and pass that TestNavHostController to the MoodTrackerApp composable.

MoodTrackerScreenNavgationTest

Step 5

For each navigation test, we use the name property of the MoodTrackerScreen enum items to check that the current destination route of the navigation controller is correct.

Write a helper function that you can call whenever you want to make such an assertion.

Create an empty Kotlin file in the test directory called ScreenAssertions.

ScreenAssertions

Add an extension function to the NavController class called assertCurrentRouteName() and pass a string for the expected route name.

Assert that the expectedRouteName is equal to the destination route of the nav controller’s current back stack entry.

ScreenAssertions

Step 6

Write a test to verify that the Start Mood Tracker screen is the current destination route when the app starts.

Create a function called moodTrackerNavHost_verifyStartDestination() and annotate it with @Test.

MoodTrackerScreenNavgationTest

Step 7

The Start Mood Tracker screen lacks a button because there is nowhere to navigate back from this screen since it is the initial screen.

Write a test to verify that that confirms the Start Mood Tracker screen doesn’t have a Back button.

Create a function called moodTrackerNavHost_verifyBackNavigationNotShownOnStartMoodTrackerScreen() and annotate it with @Test.

Create a variable in the test function with the value of the R.string.back_button resource and assert that a node with this content description does not exist on the screen.

MoodTrackerScreenNavgationTest

Step 8

Create an empty Kotlin file called ComposeRuleExtensions in the test directory.

ComposeRuleExtensions

Write an extension function to reduce the amount of code you write when finding a UI component by its string resource.

ComposeRuleExtensions

Step 9

Clicking on the Start Mood Tracker button in the Start Mood Tracker screen triggers a function that instructs the nav controller to navigate to the Choose Mood screen.

Write a test to click a button to trigger this navigation and verify that the destination route is the Choose Mood screen.

Create a function called moodTrackerNavHost_clickStartMoodTracker_navigatesToChooseMoodScreen() and annotate it with @Test.

Find the Start Mood Tracker button by its string resource id and perform a click action on it.

Assert that the current route name is the Choose Mood screen name.

ComposeRuleExtensions

Step 10

We tested navigation to the Choose Mood screen, now we will create a function to the Choose Mood screen so we don’t have to repeat this code for future tests.

Create a function called navigateToChooseMoodScreen().

Write a command to find the Start Mood Tracker button and perform a click action on it.

The Submit button on the Choose Mood screen will not be clickable until a mood is chosen. This function is only meant to prepare the UI for navigation. After you call this function, the UI should be in a state in which the Submit button is clickable.

Find a node in the UI with the R.string.happy string and perform a click action on it to select it.

MoodTrackerScreenNavgationTest

Step 11

Clicking on the Submit button in the Choose Mood screen triggers a function that instructs the nav controller to navigate to the Mood Checkout screen.

Write a test to click a button to trigger this navigation and verify that the destination route is the Mood Checkout screen.

Create a function called moodTrackerNavHost_clickSubmitOnChooseMoodScreen_navigatesToMoodCheckoutScreen() and annotate it with @Test.

Recall that the Submit button on the Choose Mood screen will not be clickable until a mood has been chosen. Call the navigateToChooseMoodScreen() function, so the UI will come to a state where the Submit button is clickable.

Find the Submit button by its string resource id and perform a click action on it.

Assert that the current route name is the Mood Checkout screen name.

MoodTrackerScreenNavgationTest

Step 12

Test screens beyond the Start Mood Tracker screen, and verify the Back button functionality to make sure it directs navigation to the previous screen.

Create a helper function to find and click the Back button.

MoodTrackerScreenNavgationTest

Create a function called moodTrackerNavHost_clickBackOnChooseMoodScreen_navigatesToMoodTrackerScreen() and annotate it with @Test.

Call the navigateToChooseMoodScreen() and performNavigateBack() functions.

Assert that the current route name is the Start Mood Tracker screen name.

MoodTrackerScreenNavgationTest

Run Tests

We already tested a part of the Mood Tracker app navigation. However, there are more navigation states to test. With the tests we’ve done so far, you now know how to write tests for other navigation states. You can find all test cases in the source code.

Press the Run test icon to run all tests in the MoodTrackerScreenNavgationTest class.

Run Test

You can see the test results below.

Test Output

Congratulations, all tests passed!

Conclusion

Now we know how to test the Jetpack Navigation component. Testing is an integral part of the app development process. With the tests you write, you can verify the accuracy, functional behavior, and usability of your app. As you continue to develop Android apps, don’t forget to write tests with your feature code!

--

--

Emine İNAN
Huawei Developers

Android Developer by day, Android Developer by night. @Huawei