是否有可能停止空闲以等待AsyncTask完成?

3
我正在尝试为我的项目设置一个测试——测试当我的应用程序执行服务器请求时,进度条是否显示。
被测试的代码使用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空闲状态,以便在服务器阻塞应用程序逻辑流程时执行验证。
(更改被测试的代码不是一个选项)
有人可以帮忙吗?
1个回答

1

所以...这是我得出的答案以及一些背后的工作:

Espresso(具体来说是对onView()onData()injectEventActions的调用)使用UiControllerImpl.loopMainThreadUntilIdle()等待直到所有“空闲引起”的信号为false。它循环遍历AsyncTask、CompatAsyncTask和名为dynamicIdle的东西,以使它们都处于空闲状态。

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

loopMainThreadUtilIdle()检查IdleNotifier以检查这三个元素的空闲状态。显然,如果您想停止espresso等待AsyncTask,那么asyncIdle特别重要。

IdleNotifier类被馈入UiControllerImpl中的构造函数 - 这是通过dagger进行的,因此您需要查看使用提供程序获取构造参数并将其传递到UiControllerProvider以构造它的DaggerBaseLayerComponent

所有这些类中的内容都被严格锁定。方法和类可见性通常受到保护或包私有和final。

我找到的唯一方法是创建自己的Espresso.java类(onView()和onData()),使用自定义的DaggerBaseLayerComponent,从而使我可以使用自己的Providers或自己的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方法来设置Instrumentation的内部状态:
// Used to give access to Whitebox
androidTestImplementation 'org.powermock:powermock-reflect:1.6.5'

就是这样了!很容易对吧?

(请告诉我它比这更容易,如何做到的!!)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接