mercredi 2 décembre 2020

Basic testing NavigationController in Android

I'm currently new to testing, so I decided to start off with some basic stuff.

I handle all my navigations from a DrawerLayout that is connected to an Activity.

So for my testing I launch an ActivityScenarioRule, create a testNavController object and then I set this testNavController to the current view that handles the navigation (The container fragment).

So the test consists on opening the drawer, clicking on menu item(Will navigate to a fragment) and therefore check if navigated to the fragment.

Then I check if that happened, but the testNavController stays on the same destination which is weird because it performs the click, so I decided to check the navController (The real one inside the activity), and it shows me that navigated to the correct fragment.

Here's the needed code:

@LargeTest
@RunWith(AndroidJUnit4::class)
class MapsActivityTest {
    @get:Rule
    var activityScenarioRule = ActivityScenarioRule(MapsActivity::class.java)

    @Test
    fun clickOnDrawerMaps_NavigateToAboutAppFragment() {
        //Create TestNavHostController
        val testNavController = TestNavHostController(ApplicationProvider.getApplicationContext())

        UiThreadStatement.runOnUiThread { // This needed because it throws a exception that method addObserver must be called in main thread
            testNavController.setGraph(R.navigation.nav_graph)
        }
        
        val scenario = activityScenarioRule.scenario
        var navcontroller : NavController? = null
        scenario.onActivity {mapsActivity ->
            navcontroller = mapsActivity.navController //Get the real navController just to debug
            mapsActivity.navController = testNavController //Set the test navController
            Navigation.setViewNavController(mapsActivity.binding.containerFragment, testNavController)
        }

        onView(withId(R.id.drawerLayout)).perform(DrawerActions.open()).check(matches(isOpen()))
        onView(withId(R.id.aboutAppFragment)).perform(click())
        assertThat(testNavController.currentDestination?.id).isEqualTo(R.id.aboutAppFragment)
    }
}

In the example they use a Fragment, which they set the fragment.requireView() on the launch of the fragment, but I think it's exactly the same.

What am I doing wrong here?

Aucun commentaire:

Enregistrer un commentaire