Android 协同路由:覆盖OKHttp';使调度程序使用异步任务';s ThreadPoolExecutor,以便Espresso可以成功断言

Android 协同路由:覆盖OKHttp';使调度程序使用异步任务';s ThreadPoolExecutor,以便Espresso可以成功断言,android,retrofit2,android-espresso,okhttp3,kotlin-coroutines,Android,Retrofit2,Android Espresso,Okhttp3,Kotlin Coroutines,我正在迁移一个应用程序,该应用程序使用改装与协同程序一起工作。该应用程序有一些UAT失败,因为Espresso没有等待协同程序完成并立即断言 默认情况下,coroutinecaladapterfactory使用OkHttp的Dispatcher执行异步请求,但Espresso仅监视UIThread和AsyncTaks线程池。我想到的一个解决方案是强制OkHttp的调度器使用AsyncTask的ThreadPoolExecutor val dispatcher = Dispatcher(Async

我正在迁移一个应用程序,该应用程序使用
改装
与协同程序一起工作。该应用程序有一些UAT失败,因为Espresso没有等待协同程序完成并立即断言

默认情况下,
coroutinecaladapterfactory
使用OkHttp的
Dispatcher
执行异步请求,但
Espresso
仅监视UI
Thread
AsyncTaks
线程池。我想到的一个解决方案是强制
OkHttp
的调度器使用
AsyncTask
ThreadPoolExecutor

val dispatcher = Dispatcher(AsyncTask.THREAD_POOL_EXECUTOR as ExecutorService)
okHttpClientBuilder.dispatcher(dispatcher)
这似乎有效,测试通过了


这是个坏主意吗?注册
IdlingResource
还是一个更好的选择吗?

如果没有更多关于您的设置的详细信息,我不确定这些信息是否有帮助,但我会提到一些可能对您的测试有帮助的提示:

转换遗嘱执行人 您也可以使用另一种方法,从任何执行器创建协同路由调度程序,方法是:

AsyncTask.THREAD_POOL_EXECUTOR.asCoroutineDispatcher()
当然,这可以在任何地方使用,比如
Dispatchers.Main
,这意味着您可以从这个范围创建一个范围,并从这个范围启动您的协同程序,而Espresso应该监控底层执行器池的完成情况。例如:

...
val espressoScope = CoroutineScope(AsyncTask.THREAD_POOL_EXECUTOR.asCoroutineDispatcher())
...
espressoScope.launch { api.getBooks() }
类似地,您可以执行以下操作:

val asyncTaskContext = AsyncTask.THREAD_POOL_EXECUTOR.asCoroutineDispatcher()
withContext(asyncTaskContext) {
    api.getBooks()
}

// OR:

@Test
fun someAndroidTest() = runBlocking(asyncTaskContext) {
    // espresso logic
}

加入工作(推荐) 最后但并非最不重要的一点是,您可以加入在测试中创建的任何作业,测试将等待作业完成后再退出。这听起来像是在您的情况下最有帮助的方法,因为您真的只想等到协同程序完成:

@Test
fun `first book has a title`() = runBlocking {
    launch {
        // run a function that suspends and takes a while
        val firstBook = api.getAllBooks().first()
        assertNotNull(firstBook.title)
    }.join()
}

那么可以使用AsyncTask线程池吗?我知道协程调度程序针对手头的任务进行了优化(即Dispatcher.IO针对IO任务进行了优化),但我不知道AsyncTask的线程池是否也进行了优化。我认为Google不推荐使用
AsyncTask
api?