我正在尝试为现有应用程序编写一些测试。我想为测试提供一个测试Application类,我遵循示例here,因为我也使用Dagger进行DI。
但是,如果测试中的活动是ActionBarActivity,我会收到以下异常:
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
我的测试类如下所示:
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中显示如下:
<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。
由于我无法找到问题的原因,我也玩了清单,build.gradle等等。现在,我只是坚持这个,我想不出别的什么。
This post也可能与问题有关,但也没有任何评论。并且this post似乎也有类似的问题,但是那里的解决方案并不适合我,因为我不希望真正的应用程序与活动一起启动。
修改:
我已经创建了一个简单的单独项目,以便隔离问题。
首先,我为一个扩展ActionBarActivity的Activity编写了一个ActivityUnitTestCase。它运作良好。
之后,我尝试添加更多活动,使它们成为彼此的父级。(因此它看起来像我的实际项目)。这也很好。
最后,我添加了更多ActivityUnitTestCase类,其中包含与我的实际项目不同的活动,所有活动都扩展了ActionBarActivity,并为所有活动提供了相同的设置,并在两个设备上运行测试,一个是模拟器(Genymotion)和另一个是我的物理设备。 (Nexus 4)
测试都在模拟器上给出了NameNotFoundException。除了其中一项测试外,所有测试都在物理设备上传递,这让我更加困惑。
答案 0 :(得分:10)
这一切都归结为ActivityUnitTestCase
中的bug。
使用ActivityUnitTestCase.startAcitvity()
构建的活动具有指向应用程序包的 componentName 。因此,当ActionBarActivity
检查父活动以更新Up符号时,如果活动不在应用程序“root”包中,则测试会崩溃。
幸运的是,问题描述中提出的解决方法工作正常,因此在修复此问题之前,只需制作ActivityUnitTestCase
的本地副本,更新 componentName 定义为的行在下面,并确保您的测试用例扩展该类而不是原始的ActivityUnitTestCase
。
// replace this line
new ComponentName(mActivityClass.getPackage().getName(), mActivityClass.getName());
// with this
new ComponentName(getInstrumentation().getTargetContext(), mActivityClass);