Java 获取Android Instrumentation测试的当前活动
我的Android应用程序上的MainActivity检查用户是否已登录(此信息存储在SharedReferences中),如果未登录,则将用户带到LoginActivity。我尝试使用以下代码来测试这一点Java 获取Android Instrumentation测试的当前活动,java,android,automated-tests,junit3,Java,Android,Automated Tests,Junit3,我的Android应用程序上的MainActivity检查用户是否已登录(此信息存储在SharedReferences中),如果未登录,则将用户带到LoginActivity。我尝试使用以下代码来测试这一点 public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { private static final int TIME_OUT = 5000; /* milisec
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static final int TIME_OUT = 5000; /* miliseconds */
private MainActivity mMainActivity;
private Instrumentation mInstrumentation;
private SharedPreferences mLoginPrefs;
public MainActivityTest() {
super(MainActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mMainActivity = getActivity();
mInstrumentation = getInstrumentation();
mLoginPrefs = mInstrumentation.getTargetContext().getSharedPreferences(LoginActivity.PREFS_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = mLoginPrefs.edit();
// User is not logged in, so it should be redirect to LoginActivity
editor.putBoolean("logged_in", false);
editor.commit();
}
//...
public void testC_OpenLoginActivityIfUserIsNotLoggedIn() {
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);
Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);
assertNotNull(nextActivity);
nextActivity.finish();
SharedPreferences.Editor editor = mLoginPrefs.edit();
// Login the user so we can continue the tests
editor.putBoolean("logged_in", true);
editor.commit();
}
公共类MainActivityTest扩展ActivityInstrumentationTestCase2{
专用静态最终整数时间=5000;/*毫秒*/
私人活动和不活动;
私用仪器;
私有共享引用mLoginPrefs;
公共维护活动测试(){
超级(MainActivity.class);
}
受保护的void setUp()引发异常{
super.setUp();
setActivityInitialTouchMode(假);
mMainActivity=getActivity();
Minstruturement=getInstrumentation();
mLoginPrefs=mInstrumentation.getTargetContext().getSharedReferences(LoginActivity.PREFS\u NAME,Context.MODE\u PRIVATE);
SharedReferences.Editor=mLoginPrefs.edit();
//用户未登录,因此应重定向到LoginActivity
编辑器.putBoolean(“登录”,false);
commit();
}
//...
public void testC_OpenLoginActivityIfUserIsNotLoggedIn(){
ActivityMonitor monitor=mInstrumentation.addMonitor(LoginActivity.class.getName(),null,false);
Activity nextActivity=分钟执行。waitForMonitorWithTimeout(监视器,超时);
assertNotNull(nextActivity);
nextActivity.finish();
SharedReferences.Editor=mLoginPrefs.edit();
//登录用户以便我们可以继续测试
编辑器.putBoolean(“已登录”,true);
commit();
}
但这不起作用,LoginActivity打开,但waitForMonitorWithTimeout从未返回,因此我被LoginActivity卡住了(我需要返回MainActivity进行其他测试)
类似于此的代码适用于按钮单击,但此活动不会通过任何单击加载,因此我认为可能没有时间让监视器工作
我只需要一种获取实际活动的方法,这样我就可以进行断言并使其完成以继续我的测试
还有一件事:如果可能的话,我更喜欢不使用Robotium的方法。您的思路是正确的。您需要调用的方法是:
monitor.waitForActivityWithTimeout(TIME_OUT);
而不是
mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);
为了解决您的问题,首先来看两种最重要的测试方法:
Instrumentation#addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean)
Instrumentation.ActivityMonitor#waitForActivity()
根据Android API参考:
添加监视器
添加一个新的Instrumentation.ActivityMonitor,每当启动一个活动时,都会检查该监视器。。该监视器是在任何现有监视器之后添加的;只有当现有监视器都无法处理该意图时,才会命中该监视器
等待活动
阻止,直到创建与该监视器匹配的活动,并返回结果活动
现在让我们更清楚一点 addMonitor应始终在启动预期活动之前调用,不要太迟 waitForActivity应仅在启动预期活动后调用,不要太早,因为它会阻塞
回到您的代码: 你把他们两个都叫在一起,其间没有任何神奇的事情发生。所以,要么对addMonitor来说太迟,要么对waitForActivity来说太早
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);
Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);
如果调用waitForActivity为时过早,它将阻塞并失败,直到超时(因为预期的活动尚未命中),并且您将永远看不到预期的活动正在启动
如果调用addMonitor为时已晚,则监视将在启动预期活动后启动,并且此后不会再次启动预期活动,因此waitForActivity将因未命中监视器而被阻止
因此,这两种情况之间的差异是是否启动了预期的活动。对于您的情况,我认为现在调用addMonitor已经太迟了
解决方案非常简单:只需在您的登录活动开始之前将addMonitor移动到足够早的位置,或者将其移动到设置方法,如下所示:
mInstrumentation = getInstrumentation();
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);
顺便说一句,对于你的情况,有没有超时并不重要
不要忘记在不再需要监视器后将其卸下,例如:
@Override
protected void tearDown() throws Exception {
mInstrumentation.removeMonitor(monitor);
super.tearDown();
}
根据API参考资料,他所做的是正确的:waitForMonitorWithTimeout(Instrumentation.ActivityMonitor,long timeOut)和Kotlin,类名称过去到addMonitor()
应该是什么样的?我尝试了“com.蝗虫板.sdktestapp.MapActivity”
,MapActivity::class.java.name.toString()
,MapActivity::class.java.canonicalName.toString()
,以及其他,但WaitFormMonitorWithTimeout()
返回了null
。此解决方案对我的Kotlin应用程序有效,谢谢。出于某种原因,.getActivitiesInStage(已恢复)
只给了我一个空集合。这只适用于检测同一包中的活动吗?
public static Activity getCurrentActivity() {
final Activity[] currentActivity = {null};
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance()
.getActivitiesInStage(RESUMED);
if (resumedActivities.iterator().hasNext()) {
currentActivity[0] = (Activity) resumedActivities.iterator().next();
}
}
});
return currentActivity[0];
}