Search code examples
androidandroid-actionbaractionbarsherlockandroid-testing

Invoke ActionBar's Up button press from code


I am writing an Android app with ActionBar enabled. In my case I use ActionBarSherlock to provide compatibility, but I think it doesn't matter in this case.

I have an Up button displaying at the left of ActionBar in my Activity. It appears after a call to setHomeAsUpEnabled(true); and it leads to the HomeActivity.

I want to write a test case which checks that Up button press leads to that HomeActivity. I am using Robotium to write tests on UI side so I can check the class of the current Activity by following assertion solo.assertCurrentActivity(HomeActivity.class); But I have not found a way to invoke a press on an Up button.

I've tried solo.clickOnView(solo.getView(android.R.id.home)) and getInstrumentation().invokeMenuActionSync(solo.getCurrentActivity(), android.R.id.home, 0); but none of them works.

Any help would be appreciated.


Solution

  • Found a workaround myself, so posting it here in case anybody will need this. This code worked for me:

    public static void clickOnUpActionBarButton(Activity activity) {
            ActionMenuItem logoNavItem = new ActionMenuItem(activity, 0, android.R.id.home, 0, 0, "");
            ActionBarSherlockCompat absc = (ActionBarSherlockCompat) UiTestUtils.invokePrivateMethodWithoutParameters(
                    SherlockFragmentActivity.class, "getSherlock", activity);
            absc.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, logoNavItem);
        }
    

    First you need to obtain ActionBarSherlockCompat object by calling getSherlock() on SherlockFragmentActivity. This method is protected, so I used Reflection API to call it:

    public static Object invokePrivateMethodWithoutParameters(Class<?> clazz, String methodName, Object receiver) {
            Method method = null;
            try {
                method = clazz.getDeclaredMethod(methodName, (Class<?>[]) null);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, e.getClass().getName() + ": " + methodName);
            }
    
            if (method != null) {
                method.setAccessible(true);
    
                try {
                    return method.invoke(receiver, (Object[]) null);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
    
            return null;
        }
    

    You need to pass solo.getCurrentActivity() to my clickOnUpActionBarButton(Activity activity) method and Up button will be pressed.