如何在使用FragmentScenario测试片段时测试与菜单的交互

8
我正在尝试使用FragmentScenario测试一个片段。该片段有自己的菜单,动作栏上有一个添加图标,点击此菜单项会启动一个子片段,用户可以从中添加新项目。所以我想测试这个行为。然而,正如您所知,FragmentScenario在EmptyFragmentActivity中启动片段,而不是启动实际的主机活动。由于动作栏不是片段布局的一部分,而属于主机活动,因此在测试过程中动作栏和菜单甚至不可见。那么我该如何测试与菜单的交互呢?
我从官方文档中找到了这条信息:
如果您需要调用片段本身的方法,例如响应选项菜单中的选择,您可以通过实现FragmentAction来安全地执行此操作。
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEventFragment() {
        val scenario = launchFragmentInContainer<MyFragment>()
        scenario.onFragment(fragment ->
            fragment.onOptionsItemSelected(clickedItem) {
                //Update fragment's state based on selected item.
            }
        }
    }
}

然而,如何将正确的项目传递给onOptionsItemSelected回调函数?我尝试将addMenuItem定义为成员变量,并在onCreateOptionsMenu中初始化它,但它返回null。在测试期间似乎并没有调用onCreateOptionsMenu。因此,我不知道如何测试菜单与用户的交互。
2个回答

6

我通过传递一个虚拟菜单项解决了这个问题:

val scenario = launchFragmentInContainer<CategoryListFragment>(Bundle(), R.style.AppTheme)

//Create a dummy menu item with the desired item id.
val context: Context = ApplicationProvider.getApplicationContext<AndroidTestApplication>()
val addMenuItem = ActionMenuItem(context, 0, R.id.action_add, 0, 0, null)
 
 //Call onOptionsItemSelected with the dummy menu item
 scenario.onFragment { fragment ->
       fragment.onOptionsItemSelected(addMenuItem)
 }

编辑:这个解决方案在那个时候挽救了一天。但现在我更喜欢将工具栏放在片段布局中而不是活动中,特别是如果我有不同的菜单供不同的片段使用,这样我就不会在其他项目中遇到相同的问题。这也是一种可能的解决方案。


哇塞,谢谢!这是一个非常简单的解决方案,解决了一个愚蠢的问题! - or_dvir

0

你也可以使用mockito来模拟菜单项。就像这样:

val menuItemMock = mock<ActionMenuItem> {
   on { itemId } doReturn R.id.action_item
}

       
launchFragmentInContainer { YourFragment().also{ /*initialize*/ } }
.onFragment {
    it.onOptionsItemSelected(menuItemMock)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接