最终我找到了一种真正测试上下文菜单和操作栏项目内容的方法。
在先决条件下,您需要创建一个特殊的Android平台,其中包含一些内部Android类,否则这些类是不可用的。Inazaruk编写了一篇优秀的tutorial来指导如何做到这一点。
为了测试上下文菜单和操作栏项目,我们将使用以下类:
- ANDROID_SDK/sources/android-VERSION/com/android/internal/view/menu/MenuBuilder
- ANDROID_SDK/sources/android-VERSION/com/android/internal/view/menu/MenuItemImpl
请注意,内部类可能随时更改。这可能会导致此单元测试失败!
为了访问这些类中的私有字段,我们将使用一个辅助函数:
private Object getValueForDeclaredField(Object sourceObject,
String fieldName) {
if (sourceObject == null) {
throw new RuntimeException(
"Error in function getValueForDeclaredField. "
+ "Source object can not be null.");
}
if (fieldName == null || fieldName.trim().isEmpty()) {
throw new RuntimeException(
"Error in function getValueForDeclaredField. "
+ "Fieldname can not be null or empty.");
}
Field field = null;
try {
field = sourceObject.getClass().getDeclaredField(fieldName);
} catch (Exception e) {
throw new RuntimeException(
"Error in function getValueForDeclaredField. Field '"
+ fieldName
+ "' does not exist in class '"
+ sourceObject.getClass().getName()
+ "'. Android implementation may have been changed. "
+ "Please check this reflection.");
}
field.setAccessible(true);
Object targetObject = null;
try {
targetObject = field.get(sourceObject);
} catch (IllegalAccessException e) {
throw new RuntimeException(
"Error in function getValueForDeclaredField. Value for field '"
+ fieldName
+ "' in class '"
+ sourceObject.getClass().getName()
+ "' can not be retrieved. "
+ "Android implementation may have been changed. "
+ "Please check this reflection.");
}
return targetObject;
}
使用上面的辅助函数,我们现在可以使用以下代码检查视图的上下文菜单的内容。
final int EXP_NUMBER_OF_CONTEXT_ITEMS = 1;
final String EXP_CONTEXT_ITEM_0_TITLE = "YOUR TITLE FOR CONTEXT ITEM 0";
ContextMenuBuilder contextMenuBuilder = new ContextMenuBuilder(
mActivity);
assertNotNull("Context menu is found", contextMenuBuilder);
MenuDialogHelper contextMenuDialogHelper = contextMenuBuilder.show(
YOUR_VIEW_HERE, view.getWindowToken());
assertNotNull("ContextMenuDialogHelper is created",
contextMenuDialogHelper);
ContextMenuBuilder menu = (ContextMenuBuilder) getValueForDeclaredField(
contextMenuDialogHelper, "mMenu");
assertNotNull("ContextMenu is available", menu);
assertEquals("Number of items in context menu",
EXP_NUMBER_OF_CONTEXT_ITEMS, menu.size());
assertEquals("Title of item 0", EXP_CONTEXT_ITEM_0_TITLE,
menu.getItem(0).toString());
contextMenuDialogHelper.dismiss();
使用上面的辅助函数,我们现在可以使用以下代码检查操作栏和活动菜单的内容。
public void testActionBar() {
final String EXP_TITLE_ACTION_BAR = "YOUR ACTION BAR TITLE HERE";
final int EXP_NUMBER_OF_ACTION_ITEMS = 2;
final String EXP_ACTION_0_TITLE = "YOUR TITLE FOR ACTION BAR ITEM 0";
final String EXP_ACTION_1_TITLE = "YOUR TITLE FOR ACTION BAR ITEM 1";
ActionBar actionBar = mActivity.getActionBar();
assertNotNull("Action bar is defined", actionBar);
ViewGroup mActionView = (ViewGroup) getValueForDeclaredField(actionBar,
"mActionView");
assertNotNull("Action view exists", mActionView);
MenuBuilder mOptionsMenu = (MenuBuilder) getValueForDeclaredField(
mActionView, "mOptionsMenu");
assertNotNull("Options menu exists", mOptionsMenu);
ArrayList<MenuItemImpl> mActionItems = (ArrayList<MenuItemImpl>)
getValueForDeclaredField(mOptionsMenu, "mActionItems");
assertEquals("Number of action items", EXP_NUMBER_OF_ACTION_ITEMS,
mActionItems.size());
MenuItemImpl action = mActionItems.get(0);
assertEquals("Title of action item 0", EXP_ACTION_0_TITLE,
action.getTitle());
assertTrue("Action item 0 is visible", action.isVisible());
action = mActionItems.get(1);
assertEquals("Title of action item 1", EXP_ACTION_1_TITLE,
action.getTitle());
ArrayList<MenuItemImpl> mNonActionItems = (ArrayList<MenuItemImpl>)
getValueForDeclaredField(mOptionsMenu, "mNonActionItems");
assertEquals("Number of non action items",
mNonActionItems.size(), 1);
}