是否可以停止空闲以完成AsyncTask?

时间:2019-01-11 19:27:13

标签: android android-asynctask android-espresso

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

被测代码使用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 个答案:

答案 0 :(得分:1)

所以...这是我已经得出的答案,并且有一些解决方法:

Espresso(特别是对onView()onData()injectEventActions的调用)使用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'

就是这样!容易吧?

请告诉我,这比这和操作要容易!