我正在尝试为我的项目设置测试-以测试我的应用执行服务器请求时是否显示进度条。
被测代码使用AsyncTask
进行网络调用。
我创建了一个阻止服务器(MockWebServer
)来捕获并保留网络呼叫-它接收请求,但直到我呼叫“。release()
”时才提供响应。这使我可以在服务器响应发生之前进行验证。
我的逻辑是这样的:
// Mock server will catch the next network request
BlockingServer blockingServer = createBlockingServer();
// onResume() activity performs network request and shows Progress Spinner
activityTestRule.launchActivity(null);
// onView() waits on UiController.loopUntilIdle() <- Fails here due to timeout.
onView(withId(progressBar)).check(matches(isDisplayed()));
// Tells the server to respond to the network request
blockingServer.release();
onView(withId(progressBar)).check(matches(not(isDisplayed())));
我的问题是,由于被测代码对服务器请求使用AsyncTask,因此Espresso自然会在验证调用(onView()
)上阻塞,以便在验证之前等待AsyncTask完成。
我需要的是在等待AsyncTask的过程中暂时停止Espresso空闲,以便在服务器阻止应用逻辑流时执行验证。
(不能更改测试代码)
有人可以帮忙吗?
答案 0 :(得分:1)
所以...这是我已经得出的答案,并且有一些解决方法:
Espresso(特别是对onView()
,onData()
,injectEvent
和Actions
的调用)使用UiControllerImpl.loopMainThreadUntilIdle()
等待所有“导致空闲”的信号都为假。它将遍历AsyncTask,CompatAsyncTask和称为dynamicIdle
的东西,使其全部处于空闲状态。
此方法返回时,主流继续。
loopMainThreadUtilIdle()
检查IdleNotifier
来检查这三个元素中每个元素的空闲状态。显然,如果您想停止等待AsyncTask的意式浓缩咖啡,asyncIdle
对您特别有用。
IdleNotifier
类在构造时被馈入UiControllerImpl
-这是通过匕首进行的,因此您需要查看DaggerBaseLayerComponent
,它使用提供程序来获取构造参数并传递将它们放入UiControllerProvider进行构建。
所有这些类中的所有内容都被严格锁定。方法和类的可见性通常是受保护的,或者是包私有的,并且是最终的。
我发现的唯一方法是创建自己的Espresso.java类(onView()和onData()),该类使用自定义DaggerBaseLayerComponent允许我使用:我自己的提供程序或我自己的UiController。
但是我发现这并不能解决整个问题。还有另一种机制需要编码-当您开始活动时,它们在Instrumentation类中使用waitForIdleSync
。通常,这是gradle文件中提供的Runner。我创建了自己的AndroidJUnitRunner,并在gradle中提供了此功能,以允许我从waitForIdleSync
返回命令。
最后,在Instrumentation基类的startActivitySync
中,它使用ActivityWaiter
对象的数组来阻止launchIntent()
的调用。我想不出一种避免这种情况的合理方法,因此我在Runner中作弊并创建了这种方法:
public void clearActivityWaitQueue() {
Object mSync = Whitebox.getInternalState(this, "mSync");
List mWaitingActivities = Whitebox.getInternalState(this, "mWaitingActivities");
if (mSync != null && mWaitingActivities != null) {
mWaitingActivities.clear();
synchronized (mSync) {
mSync.notifyAll();
}
}
}
它使用PowerMock为我提供方便的Whitebox方法来设置检测的内部状态:
// Used to give access to Whitebox
androidTestImplementation 'org.powermock:powermock-reflect:1.6.5'
就是这样!容易吧?
(请告诉我,这比这和操作要容易!)