Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NameNotFoundException at ActivityUnitTestCase with ActionBarActivity

I am trying to write some tests for an existing application. I wanted to supply a test Application class to the tests and I followed the example here, since I am also using Dagger for DI.

However, if the activity under test is an ActionBarActivity, I get the following exception:

java.lang.IllegalArgumentException: android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{mypackage.view.activity/mypackage.view.activity.MyActivity}
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:282)
at android.support.v7.app.ActionBarActivityDelegate.onCreate(ActionBarActivityDelegate.java:116)
at android.support.v7.app.ActionBarActivityDelegateICS.onCreate(ActionBarActivityDelegateICS.java:57)
at android.support.v7.app.ActionBarActivity.onCreate(ActionBarActivity.java:98)
at mypackage.view.activity.MyActivity.onCreate(MyActivity.java:68)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.test.ActivityUnitTestCase.startActivity(ActivityUnitTestCase.java:158)
at mypackage.MyActivityTest.test(MyActivityTest.java:89)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
Caused by: android.content.pm.PackageManager$NameNotFoundException: ComponentInfo{mypackage.view.activity/mypackage.view.activity.MyActivity}
at android.app.ApplicationPackageManager.getActivityInfo(ApplicationPackageManager.java:242)
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:298)
at android.support.v4.app.NavUtils.getParentActivityName(NavUtils.java:279)
... 21 more

My test class looks like follows:

public class MyActivityTest extends ActivityUnitTestCase<MyActivity> {

    ...

    public MyActivityTest() {
        super(MyActivity.class);
    }

    private Context context;

    private TestBaseApplication application;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        context = new ContextThemeWrapper( getInstrumentation().getTargetContext(), R.style.Theme_AppCompat){
            @Override
            public Context getApplicationContext() {
                return application;
            }
        };
        application = new TestBaseApplication( context);
        setApplication(application);

        ...
    }

    public void test() throws InterruptedException {
        setActivityContext( context);
        Intent intent = new Intent( context, MyActivity.class);
        startActivity(intent, null, null);
        ...
    }
}

The activity appears in the AndroidManifest as follows:

<activity
            android:name=".view.activity.MyActivity"
            android:icon="@drawable/actionbar_logo"
            android:screenOrientation="portrait"
            android:parentActivityName="mypackage.ParentActivity">
            <meta-data android:name="android.support.PARENT_ACTIVITY"
                android:value="mypackage.ParentActivity"/>
        </activity>

After some troubleshooting, I tried running the example at the link above and it works just fine, even when I change the activity to extend ActionBarActivity.

Since I wasn't able to find the cause of the problem, I also played around with the manifest, build.gradle, etc. Now, I am just stuck with this and I cannot think of anything else.

This post may also be close to related to the problem, but there is not any comment on that one either. And this post also seemed to have similar problem but the solution there doesn't work me as I don't want the real application to be launched with the activity.

EDIT:

I've created a simple separate project, in order to isolate the issue.

First I've written an ActivityUnitTestCase for an Activity which extends ActionBarActivity. It worked fine.

After that, I've tried adding few more activities, making them parent of each other.( so that it looks like my actual project). And that worked fine too.

Lastly, I've added more ActivityUnitTestCase classes with different activities from my actual project, all extending ActionBarActivity, with same setup for all of them , and run the tests on two devices, one being an emulator (Genymotion) and the other is my physical device. (Nexus 4)

Tests all gave the NameNotFoundException on the emulator. All but one of the tests passed on the physical device, which made me even more confused.

like image 378
Emre Dirican Avatar asked Jul 15 '14 14:07

Emre Dirican


1 Answers

It all comes down to this bug in ActivityUnitTestCase.

Activities built using ActivityUnitTestCase.startAcitvity() have a componentName pointing to the application package. So when ActionBarActivity checks for a parent activity to update the Up symbol, the test crashes if the activity is not in the app 'root' package.

Fortunately the workaround proposed in the issue description works just fine, so until this is fixed, just make a local copy of ActivityUnitTestCase, update the line in which the componentName is defined as below, and make sure your test cases extend that class instead of the original ActivityUnitTestCase.

// replace this line
new ComponentName(mActivityClass.getPackage().getName(), mActivityClass.getName());

// with this
new ComponentName(getInstrumentation().getTargetContext(), mActivityClass);
like image 50
ivagarz Avatar answered Sep 19 '22 01:09

ivagarz