TransWikia.com

Android - Testing navigation with NavigationComponent

Stack Overflow Asked by SomeKoder on January 3, 2022

I’m having trouble testing my navigation with NavigationComponent, Espresso and Mockito. I have this simple test:

@Test
fun testNavigation(){

    val mockNavController = mock(NavController::class.java)

    val firstScenario = launchFragmentInContainer<FirstFragment>()

    firstScenario.onFragment { fragment ->
        Navigation.setViewNavController(fragment.requireView(), mockNavController)
    }

    val expectedBundle = bundleOf(ARG_A to true)

    onView(withId(R.id.button)).perform(click())

    verify(mockNavController).navigate(R.id.action_first_fragment_to_second_fragment, expectedBundle)
}

The test fails with this error:

Argument(s) are different! Wanted:
navController.navigate(
2131361850,
Bundle[{ARG_A=true}]
);
-> at FirstFragmentTest.testNavigation(FirstFragmentTest.kt:60)

Actual invocation has different arguments:
navController.navigate(
2131361850,
Bundle[{ARG_A=true}]
);
-> at FirstFragment$onViewCreated$2.onClick(FirstFragment.kt:67)

The arguments and id are exactly the same, the only difference is that last line in the error showing where the on click was invoked. Also, the onClick() method in my test doesn’t even seem to open the second fragment. It just stays on the first fragment.

Does someone know what’s going wrong?
Thanks in advance!

One Answer

Bundles can contain different kinds of information, of different types and sizes.

equals method of Bundle class is just default implementation that compares two objects by reference.

You'll have to implement comparison by yourself or use already approved solution.

I've found a static method of Bundle superclass BaseBundle called kindOfEquals:

/**
 * Does a loose equality check between two given {@link BaseBundle} objects.
 * Returns {@code true} if both are {@code null}, or if both are equal as per
 * {@link #kindofEquals(BaseBundle)}
 *
 * @param a A {@link BaseBundle} object
 * @param b Another {@link BaseBundle} to compare with a
 * @return {@code true} if both are the same, {@code false} otherwise
 *
 * @see #kindofEquals(BaseBundle)
 *
 * @hide
 */
public static boolean kindofEquals(BaseBundle a, BaseBundle b) {
    return (a == b) || (a != null && a.kindofEquals(b));
}

But because it does loose equality check that may be not the desired solution.

Update

BaseBundle is not public but you can still check its kindOfEquals implementation and take it as an example.

Answered by Jenea Vranceanu on January 3, 2022

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP