Espresso不会等待AsyncTask完成

时间:2017-02-16 14:38:43

标签: java android testing android-asynctask android-espresso

根据Espresso文档,检测测试应自动等待AsyncTasks完成。但它不起作用。我创建了这个简单的测试用例:

package foo.bar;

import android.os.AsyncTask;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.LargeTest;
import android.support.test.rule.UiThreadTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ExampleInstrumentedTest {

    private static final String TAG = "ExampleInstrumentedTest";

    @Rule public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();

    @Test
    @UiThreadTest
    public void testAsyncTask() throws Throwable {
        Log.d(TAG, "testAsyncTask entry");
        uiThreadTestRule.runOnUiThread(() -> new AsyncTask<String, Void, Integer>() {
            @Override
            protected Integer doInBackground(String... params) {
                Log.d(TAG, "doInBackground() called with: params = [" + params + "]");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ignored) {
                }
                return params.length;
            }

            @Override
            protected void onPostExecute(Integer integer) {
                Log.d(TAG, "onPostExecute() called with: integer = [" + integer + "]");
                assertEquals(3, (int) integer);
                throw new RuntimeException("this should fail the test");
            }
        }.execute("One", "two", "three"));
        Log.d(TAG, "testAsyncTask end");
    }
}

返回UI线程时测试失败但总是成功。 这是测试的logcat输出:

I/TestRunner: started: testAsyncTask(foo.bar.ExampleInstrumentedTest)
D/ExampleInstrumentedTest: testAsyncTask entry
D/ExampleInstrumentedTest: testAsyncTask end
I/TestRunner: finished: testAsyncTask(foo.bar.ExampleInstrumentedTest)
D/ExampleInstrumentedTest: doInBackground() called with: params = [[Ljava.lang.String;@8da3e9]

正如您所见,在执行背景方法之前,测试已完成。 如何让测试等待它?

3 个答案:

答案 0 :(得分:7)

事实证明Espresso 确实等待AsyncTasks完成,但只有才能进行视图互动。

原因是Espresso在UiController#loopMainThreadUntilIdle()方法期间等待任务,该方法在每次视图交互时自动调用窗帘。因此,尽管我的测试不需要任何观点或活动,但我必须创建它们。

这就是现在的工作测试:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ExampleInstrumentedTest {

    private static final String TAG = "ExampleInstrumentedTest";

    @Rule public ActivityTestRule<TestingActivity> activityTestRule = new ActivityTestRule<>(
        TestingActivity.class, false, false);

    @Before
    public void setUp() throws Exception {
        activityTestRule.launchActivity(new Intent());
    }

    @Test
    public void testAsyncTask() throws Throwable {
        Log.d(TAG, "testAsyncTask entry");

        AsyncTask<String, Void, Integer> task = new AsyncTask<String, Void, Integer>() {

            @Override
            protected Integer doInBackground(String... params) {
                Log.d(TAG, "doInBackground() called with: params = [" + params + "]");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ignored) {
                }
                return params.length;
            }

            @Override
            protected void onPostExecute(Integer integer) {
                Log.d(TAG, "onPostExecute() called with: integer = [" + integer + "]");
                assertEquals(3, (int) integer);
                throw new RuntimeException("this should fail the test");
            }
        };
        task.execute("One", "two", "three");
        Espresso.onView(withId(android.R.id.content)).perform(ViewActions.click());

        Log.d(TAG, "testAsyncTask end");
    }
}

最重要的新行是:Espresso.onView(withId(android.R.id.content)).perform(ViewActions.click());因为它会导致Espresso等待AsyncTask后台操作完成。

TestingActivity只是一个空的活动:

public class TestingActivity extends Activity {

}

答案 1 :(得分:0)

您是否尝试过使用Espresso.onIdle()

从文档中

  

循环主线程,直到应用程序空闲为止。

     

仅对不与任何UI元素交互但需要Espresso主线程同步的测试调用此方法!此方法主要用于在Espresso之上构建的测试实用程序和框架。

答案 2 :(得分:-2)

它按预期工作。由于您在Thread.sleep()内调用doInBackground(),因此它不会在UI线程中休眠。将睡眠代码移动到onPostExecute,它应该按预期工作。