【问题标题】:Android Unit Test cases for RecyclerView in FragmentFragment中RecyclerView的Android单元测试用例
【发布时间】:2021-09-03 10:36:46
【问题描述】:

我正在尝试在片段中为 recyclerview 编写测试,但无论我尝试哪种解决方案,似乎总是遇到相同的错误 (androidx.test.espresso.NoMatchingRootException)。

错误

androidx.test.espresso.NoMatchingRootException: Matcher 'with decor view is <DecorView@814c399[]>' did not match any of the following roots: [Root{application-window-token=android.view.ViewRootImpl$W@5c6165e, window-token=android.view.ViewRootImpl$W@5c6165e, has-window-focus=false, layout-params-type=1, layout-params-string={(0,0)(fillxfill) sim={adjust=pan} ty=BASE_APPLICATION wanim=0x10302fe
  fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
  pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=1080, height=2280, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) sim={adjust=pan} ty=BASE_APPLICATION wanim=0x10302fe
  fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
  pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}}]

ListTestFragment.java

public class ListTestFragment {
    private ListTestFragment fragment;

    @Rule
    public ActivityTestRule<BottomNavigationActivity> activityActivityTestRule = new ActivityTestRule<BottomNavigationActivity>(BottomNavigationActivity.class);

    @Before
    public void setUp() {
        activityActivityTestRule.getActivity().getSupportFragmentManager().beginTransaction();
        activityActivityTestRule.getActivity().openChatFragment(null);
        fragment = activityActivityTestRule.getActivity().chatFragment;
    }

    @BeforeClass
    public static void testClassSetup() {
        System.out.println("Getting test class ready");
    }

    @AfterClass
    public static void testClassCleanup() {
        System.out.println("Done with tests");
    }

    @After
    public void cleanup() {
        System.out.println("Done with unit test!");
    }


    @Test
    public void testSampleRecyclerVisible() {
        Espresso.onView((withId(R.id.container)))
                .inRoot(RootMatchers.withDecorView(
                        Matchers.is(activityActivityTestRule.getActivity().getWindow().getDecorView())))
                .check(matches(isDisplayed()));
    }

    @Test
    public void testCaseForRecyclerClick() {
        Espresso.onView(ViewMatchers.withId(R.id.recyclerview))
                .inRoot(RootMatchers.withDecorView(
                        Matchers.is(activityActivityTestRule.getActivity().getWindow().getDecorView())))
                .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
    }

    @Test
    public void testCaseForRecyclerScroll() {
        // Get total item of RecyclerView
        RecyclerView recyclerView = activityActivityTestRule.getActivity().findViewById(R.id.recyclerview);
        int itemCount = 20;

        // Scroll to end of page with position
        Espresso.onView(ViewMatchers.withId(R.id.recyclerview))
                .inRoot(RootMatchers.withDecorView(
                        Matchers.is(activityActivityTestRule.getActivity().getWindow().getDecorView())))
                .perform(RecyclerViewActions.scrollToPosition(itemCount - 1));
    }
}

openChatFragment() 方法

public void openChatFragment(CloseDialogFragmentInterface closeDialogFragmentInterface) {
        chatFragment = new ChatListFragment();
        Utils.openFragment(this, chatFragment, false, tasksTitle + "Fragment");
    }

openFragment() 方法

public static void openFragment(AppCompatActivity appCompatActivity, Fragment fragment, boolean addTobackStack, String tag) {
    try {

        FragmentManager fm = appCompatActivity.getSupportFragmentManager();
        String fragmentName = fragment.getClass().getSimpleName();
        fm.popBackStack(fragmentName, FragmentManager.POP_BACK_STACK_INCLUSIVE);

        FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        if (addTobackStack) {
            fragmentTransaction.addToBackStack(fragmentName);
        }
        fragmentTransaction.replace(R.id.container, fragment, tag);
        fragmentTransaction.commit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我认为这与查找 recyclerview 的 id 有关,只是无法找出正确的方法。 任何帮助表示赞赏。谢谢

【问题讨论】:

  • 请提供openChatFragment()的代码
  • @Zain ,我已经更新了代码
  • 调用只有一个参数null,方法签名有多个参数
  • 请检查我添加了 2 个方法,openChatFragment 使用 openFragment,我已经为这两种方法提供了代码

标签: android android-fragments android-recyclerview junit android-espresso


【解决方案1】:

如果您正在测试片段中的 UI,那么您可以内置 espresso 片段测试的方法。

使用 espresso 进行片段测试的依赖性

dependencies {
    def fragment_version = "1.3.6"

    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

要启动片段,请在您的设置方法中编写以下代码

val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)

您可以在 espresso here 中获取有关片段测试的更多信息

【讨论】:

【解决方案2】:

使用 Barista 库进行 UI 测试,这是最简单的解决方案,让一切变得更简单。 https://github.com/AdevintaSpain/Barista

在里面,尝试使用RecyclerView的测试方法:

clickListItem(R.id.list, 4);
clickListItemChild(R.id.list, 3, R.id.row_button);
scrollListToPosition(R.id.list, 4);

assertDisplayedAtPosition(R.id.list, 0, "text");
assertDisplayedAtPosition(R.id.list, 0, R.id.text_field, "text");
assertDisplayedAtPosition(R.id.list, 0, R.string.hello_world);
assertDisplayedAtPosition(R.id.list, 0, R.id.text_field, 
R.string.hello_world);
assertDrawableDisplayedAtPosition(R.id.recycler, 0, R.id.imageview, 
R.drawable.ic_barista);

【讨论】:

  • 不使用第三方库就没有解决办法
  • 您可以检查库方法以及它们是如何工作的,并使用您需要并为您工作的部分代码。
  • 好主意,让我检查一下代码,看看是否有效
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多