簡體   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