Problem with NavController when trying to run EspressoTest

Issue

I am getting this error:

IllegalStateException: View android.widget.LinearLayout{649700d V.E…… ……I. 0,0-0,0} does not have a NavController set

But this happens only on espresso tests. The code where the crash happens handles onBackPressed on my fragment:

val navController  Navigation.findNavController(view)//this line here
        requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                navController.popBackStack(R.id.homeFragment, false)
            }
        })

This is my Espresso Test:

    @Test
    fun testBackButton() {
        val mockNavController  mock(NavController::class.java)
        settingsFragmentScenario  launchFragmentInContainer()
        settingsFragmentScenario.onFragment {
            Navigation.setViewNavController(it.requireView(), mockNavController)
        }
        performClickOnViews(android.R.id.home)
        verify(mockNavController).navigate(R.id.home)
    }

If I remove my code on the fragment tests run without any error (except from what I assert wrong)

I did check: IllegalStateException: Link does not have a NavController set, but his/her problem is not same as mine.

PS: On production code this line doesn’t crash

Solution

I managed to resolve this, by replacing:

val navController  Navigation.findNavController(view)//this line here
        requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                navController.popBackStack(R.id.homeFragment, false)
            }
        })

With:

requireActivity().onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                view.findNavController().popBackStack(R.id.homeFragment, false)
            }
        })

Explenation, the nav controller is set on the view in my test using setViewNavController, thus I had to change my production code 🙂

Answered By – coroutineDispatcher

Leave a Comment