androidmockitoandroid-espressoandroid-architecture-navigationui-testing

Test Navigation Component with SafeArgs and Mockito


I'm trying to test if a fragment A calls fragment B through Navigation Component's navigate(NavDirection) method, and using Mockito. The problem is that the action from fragment A to fragment B has safe args (one object, to be exact), and when trying to do the following:

verify(navController).navigate(FragmentADirections.actionFragmentAToFragmentB(payload))

Mockito throws an "Argument(s) are different!" error, and the difference between the calls is the instance of payload. What I'm doing here is that the (mocked) viewmodel of this fragment A receives the intent extra of the activity that launched the fragment (with launchFragmentInHiltContainer helper method), and catches the payload object from it (this object is then used in the arguments of FragmentADirection's action method). This is the moment where the "other instance" is created, but I don't need Mockito to verify the equality of instances, instead I just need to check if fragment A called navigate to fragment B correctly.

Is there a way to achieve this using Mockito?

Flow of code:

  1. Fragment A calls viewmodel, passing it's activity reference
  2. viewmodel catches intent.extras with the payload
  3. viewModel calls the navigate method passing the payload caught in the previous step

P.S.: I'm using Hilt, and I'm initializing my mock instance of navController this way:

private val navController = mock(NavController::class.java)

Solution

  • Although I did not find a way to make Mockito check the difference between payload data instead of instance, I tried again using TestNavHostController as @ianhanniballake suggested, and while I was refactoring the code I noticed that when I was checking for a text in a view, instead of using R.string I was using R.id, which caused the test to fail. Now that I have corrected that, everything seems to be working just fine.

    So, for this situation, check if you are doing some wrong assertion before looking into navController.currentDestination?.id value.