繁体   English   中英

获取Android Instrumentation Test上的当前活动

[英]Get current Activity on Android Instrumentation Test

我的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问题的代码适用于按钮点击,但任何点击都不会加载此活动,所以我想也许没有时间让显示器工作。

我只需要一种方法来获取实际的Activity,这样我就可以创建一个断言并完成继续我的测试。

另外一件事:如果可能的话,我更喜欢不使用Robotium的方法。

为了解决您的问题,首先看看您测试的两个最重要的方法:

Instrumentation#addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean)
Instrumentation.ActivityMonitor#waitForActivity()

根据Android API参考:

添加监视器

添加一个新的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);

BTW,对于你的情况,超时或没有超时无关紧要。

不要忘记在不再需要后移除monitor ,例如:

@Override
protected void tearDown() throws Exception {
    mInstrumentation.removeMonitor(monitor);
    super.tearDown();
}
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];
}

你走在正确的轨道上。 您需要调用的方法是:

monitor.waitForActivityWithTimeout(TIME_OUT);

代替

mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM