使用 FragmentScenario 测试片段时如何测试与菜单的交互
How to test interactions with menu when testing fragments with FragmentScenario
我正在尝试使用 FragmentScenario 测试片段。这个片段有自己的菜单。操作栏上有一个添加图标,单击此菜单项会启动一个子片段,用户可以从中添加新项目。所以我正在尝试测试这种行为。
但是,您可能知道,FragmentScenario 在 EmptyFragmentActivity 中启动片段,而不启动真正的主机 activity。由于操作栏不是片段布局的一部分,而是属于主机 activity,因此操作栏和菜单在测试期间甚至不可见。那么如何测试与菜单的交互?
我从官方文档中找到了这条信息:
If you need to call a method on the fragment itself, such as
responding to a selection in the options menu, you can do so safely by
implementing 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 中对其进行初始化,但它 returns null。 onCreateOptionsMenu 似乎在测试期间没有被调用。所以我不知道如何测试用户与菜单的交互。
我通过传递一个虚拟菜单项解决了这个问题:
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)
}
编辑:这个解决方案当时挽救了局面。但现在我开始更喜欢将工具栏放在片段布局中,而不是 activity,特别是如果我对不同的片段有不同的菜单,所以我认为我在其他项目中没有同样的问题。这也是一个可能的解决方案。
您还可以使用 mockito 模拟菜单项。像这样:
val menuItemMock = mock<ActionMenuItem> {
on { itemId } doReturn R.id.action_item
}
launchFragmentInContainer { YourFragment().also{ /*initialize*/ } }
.onFragment {
it.onOptionsItemSelected(menuItemMock)
}
我正在尝试使用 FragmentScenario 测试片段。这个片段有自己的菜单。操作栏上有一个添加图标,单击此菜单项会启动一个子片段,用户可以从中添加新项目。所以我正在尝试测试这种行为。 但是,您可能知道,FragmentScenario 在 EmptyFragmentActivity 中启动片段,而不启动真正的主机 activity。由于操作栏不是片段布局的一部分,而是属于主机 activity,因此操作栏和菜单在测试期间甚至不可见。那么如何测试与菜单的交互?
我从官方文档中找到了这条信息:
If you need to call a method on the fragment itself, such as responding to a selection in the options menu, you can do so safely by implementing 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 中对其进行初始化,但它 returns null。 onCreateOptionsMenu 似乎在测试期间没有被调用。所以我不知道如何测试用户与菜单的交互。
我通过传递一个虚拟菜单项解决了这个问题:
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)
}
编辑:这个解决方案当时挽救了局面。但现在我开始更喜欢将工具栏放在片段布局中,而不是 activity,特别是如果我对不同的片段有不同的菜单,所以我认为我在其他项目中没有同样的问题。这也是一个可能的解决方案。
您还可以使用 mockito 模拟菜单项。像这样:
val menuItemMock = mock<ActionMenuItem> {
on { itemId } doReturn R.id.action_item
}
launchFragmentInContainer { YourFragment().also{ /*initialize*/ } }
.onFragment {
it.onOptionsItemSelected(menuItemMock)
}