我的安卓应用程序上的MainActivity会检查用户是否已登录(它存储在SharedPreferences中),如果没有登录,则将用户带到LoginActivity。我正在尝试使用以下代码来测试这一点
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();
}但是这不起作用,LoginActivity打开了,但是waitForMonitorWithTimeout再也没有返回,所以我被LoginActivity卡住了(我需要回到MainActivity来做其他的测试)。
类似于此SO Question的代码适用于按钮单击,但此活动不是由任何单击加载的,所以我在想,可能没有时间让监视器工作。
我只需要一种方法来获取实际的活动,这样我就可以进行断言并使其完成以继续我的测试。
还有一件事:如果可能的话,我更喜欢不使用Robotium的方法。
发布于 2015-01-10 05:16:21
为了解决你的问题,首先看看你的测试中最重要的两种方法:
Instrumentation#addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean)
Instrumentation.ActivityMonitor#waitForActivity()根据Android API参考:
addMonitor
添加一个新的Instrumentation.ActivityMonitor,每当启动活动时都将被检查。监视器被添加到任何现有监视器之后;只有当现有监视器本身都不能处理意图时,监视器才会被击中。
waitForActivity
阻塞,直到创建了一个与此监视器匹配的活动,并返回结果活动。
现在让我们把它说得更清楚一点。
addMonitor应该在预期的活动开始之前调用always ,永远不会太晚。
waitForActivity应该只在被启动的预期活动之后调用,永远不要太早,因为它会阻塞。
回到你的代码:
你把他们两个都叫到一起,中间没有任何魔法发生。所以对addMonitor来说要么太晚了,要么对waitForActivity来说太早了。
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);
Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);如果调用waitForActivity太早,它将阻塞并失败,直到超时(因为预期的活动尚未命中),并且您永远看不到预期的活动正在启动。
如果调用addMonitor为时已晚,则会在预期的activity启动后开始监控,此后不会再启动预期的activity,因此waitForActivity会因为监视器没有命中而阻塞。
因此,无论预期的活动是否启动,两种情况之间的差异都是。对于你的情况,我认为现在调用addMonitor已经太晚了。
解决方案非常简单:只需在LoginActivity启动之前将addMonitor移动到足够早的位置,或者将其移动到setUp方法,如下所示:
mInstrumentation = getInstrumentation();
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);顺便说一句,对于你的情况,有没有超时都无关紧要。
在不再需要monitor时,不要忘记将其删除。例如:
@Override
protected void tearDown() throws Exception {
mInstrumentation.removeMonitor(monitor);
super.tearDown();
}发布于 2018-10-27 23:09:37
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];
}发布于 2014-09-04 13:16:05
你走在了正确的道路上。您需要调用的方法是:
monitor.waitForActivityWithTimeout(TIME_OUT);而不是
mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);https://stackoverflow.com/questions/23209372
复制相似问题