是否可以停止空转以完成AsyncTask



我正在尝试为我的项目设置一个测试,以测试当我的应用程序执行服务器请求时是否显示进度条。

测试中的代码使用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空闲,以便在服务器阻塞应用程序逻辑流时执行验证。

(更改测试中的代码不是一个选项)

有人能帮忙吗?

所以。。。这是我得出的答案,并在背后进行了一些研究:

Espresso(特别是对onView()onData()injectEventActions的调用)使用UiControllerImpl.loopMainThreadUntilIdle()等待,直到所有"导致空闲"的信号都为假。它在AsyncTask、CompatAsyncTask和dynamicIdle上循环,使它们都处于空闲状态。

当此方法返回时,主流继续。

CCD_ 11检查CCD_ 12以检查这三个元件中的每一个的空闲状态。显然,如果您想停止espresso等待AsyncTask,那么asyncIdle对您特别感兴趣。

IdleNotifier类在构造时被馈送到UiControllerImpl中-这是通过dagger进行的,因此您需要查看DaggerBaseLayerComponent,它使用Providers来获取构造参数,并将它们传递到UiControllerProvider中以构造它。

所有这些类中的所有内容都被严格地锁定。方法和类的可见性通常是受保护的,或者是包私有的和最终的。

我找到的唯一方法是创建我自己的Espresso.java类(onView()和onData()),该类使用自定义DaggerBaseLayerComponent,允许我使用:我自己的Providers或我自己的UiController。

然而,我发现这并不能解决整个问题。还有一种机制需要编码——当您开始活动时,它们在Instrumentation类中使用waitForIdleSync。通常这是渐变文件中提供的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方法来设置Instrumentation的内部状态:

// Used to give access to Whitebox
androidTestImplementation 'org.powermock:powermock-reflect:1.6.5'

就这样!很简单吧?

(请告诉我它比这个更容易,以及如何!!)

最新更新