我在Android应用程序上的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的代码可用于按钮单击,但是任何单击都不会加载此活动,因此我认为监视器可能没有时间工作。
我只需要一种获取实际Activity的方法,就可以断言并使其完成以继续我的测试。
另一件事:如果可能的话,我希望不使用Robotium的方法。
最佳答案
为了解决您的问题,请首先查看两种最重要的测试方法:
Instrumentation#addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean)
Instrumentation.ActivityMonitor#waitForActivity()
根据Android API参考:
addMonitor
添加一个新的Instrumentation.ActivityMonitor,只要启动活动,就会检查。监视器将在现有监视器之后添加;仅当现有监视器都无法自己处理Intent时,该监视器才会被命中。
waitForActivity
阻止,直到创建一个活动,该活动与此监视器的匹配并返回生成的活动。
现在让我们更清楚一点。
addMonitor 应该总是在预期活动开始之前调用,永远不要太晚。
waitForActivity 应该仅在预期活动开始之后调用,永远不要太早,因为它将阻止。
返回您的代码:
您将两者同时调用,而两者之间没有发生任何魔术。因此,对于addMonitor来说为时已晚,对于waitForActivity而言为时过早。
ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false);
Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);
如果调用waitForActivity还为时过早,它将阻塞并失败,直到超时(因为尚未达到预期的活动),并且您将永远不会看到预期的活动正在启动。
如果调用addMonitor为时已晚,则监视将在启动预期活动之后开始,并且此后不再启动预期活动,因此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();
}