问题描述
根据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]
正如您所见,在执行背景方法之前,测试结束。 我怎样才能让测试等待它?
1楼
事实证明Espresso 确实等待AsyncTasks完成, 但仅在有视图交互的情况下才会完成。
原因是Espresso在方法期间等待任务,该方法在每次视图交互时在窗帘后面自动调用。 因此,尽管我的测试不需要任何视图或活动,但我必须创建它们。
这就是现在工作测试的样子:
@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
只是一个空的Activity:
public class TestingActivity extends Activity {
}
2楼
你尝试过使用吗?
来自文档:
循环主线程,直到应用程序进入空闲状态。
仅对不与任何UI元素交互的测试调用此方法,但需要Espresso的主线程同步! 此方法主要用于构建在Espresso之上的测试实用程序和框架。
3楼
它按预期工作。
由于您在doInBackground()
中调用Thread.sleep()
,因此它不会睡眠UI线程。
将睡眠代码移动到onPostExecute
,它应该按预期工作。