首页 > 解决方案 > Android - 使用 NavigationComponent 测试导航

问题描述

我在使用 NavigationComponent、Espresso 和 Mockito 测试导航时遇到问题。我有这个简单的测试:

@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)
}

测试失败并出现以下错误:

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)

参数和 id 完全相同,唯一的区别是错误中的最后一行显示了 on click 的调用位置。此外,我的测试中的 onClick() 方法似乎甚至没有打开第二个片段。它只停留在第一个片段上。

有人知道出了什么问题吗?提前致谢!

标签: androidnavigationautomated-testsmockitoandroid-espresso

解决方案


捆绑包可以包含不同类型、不同类型和大小的信息。

equals类的方法Bundle只是通过引用比较两个对象的默认实现。

您必须自己实施比较或使用已批准的解决方案

我找到了一个Bundle超类的静态方法,BaseBundle称为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));
}

但是因为它这样做loose equality check可能不是理想的解决方案。

更新

BaseBundle不公开,但您仍然可以检查其kindOfEquals实现并以它为例。


推荐阅读