在的NameNotFoundException与ActivityUnitTestCase ActionBarActivityNameNotFoundException、ActivityUnitTest

2023-09-09 21:12:04 作者:弦断花落

我试图写现有应用程序的一些测试。我想提供一个测试应用类测试,我跟着的例子here,因为我还用匕首对DI。

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.

不过,如果被测活动是ActionBarActivity,我得到以下异常:

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);
        ...
    }
}

活动出现在AndroidManifest如下:

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>

一些故障排除后,我试着运行在上面的链接的例子,它工作得很好,甚至当我更改活动延长ActionBarActivity。

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.

由于我没有能够找到问题的原因,我也与清单,的build.gradle等。现在,我只是坚持了这一点,我想不出别的发挥各地。

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帖子也可能接近相关的问题,但没有在一个任何评论无论是。和this帖子似乎也有类似的问题,但解决的办法有,因为我不希望真正的应用程序与活动推出就不起作用了我。

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.

修改

我创建了一个简单的单独的项目,以找出问题。

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

首先,我已经写了延伸ActionBarActivity一个活动的ActivityUnitTestCase。它工作得很好。

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.

最后,我增加了更多的ActivityUnitTestCase班,不同的活动,从我的实际项目中,所有扩展ActionBarActivity,具有相同的设置为所有这些,并在两个设备,一个是仿真器(Genymotion)和其他运行测试是我的物理设备。 (的Nexus 4)

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)

测试了所有的上的NameNotFoundException模拟器。但所有物理设备上通过测试之一,这让我更糊涂了。

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.

推荐答案

这一切都归结到这一点错误的 ActivityUnitTestCase

It all comes down to this bug in ActivityUnitTestCase.

使用内置活动 ActivityUnitTestCase.startAcitvity()拥有的组件名的指向应用程序包。因此,当 ActionBarActivity 检查是否有父活动更新向上的象征,测试崩溃,如果该活动没有在应用'根'包。

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.

幸运的是这个问题的说明中提出的解决办法工作得很好,所以直到这个是固定的,只是让 ActivityUnitTestCase 的本地副本,更新线路,其中的组件名的定义如下,并确保你的测试用例延长代替原有的 ActivityUnitTestCase

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);