首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为Espresso测试制作CoroutineDispatcher IdlingResource

为Espresso测试制作CoroutineDispatcher IdlingResource
EN

Stack Overflow用户
提问于 2019-06-13 23:10:27
回答 2查看 995关注 0票数 3

我正在尝试找到一种方法来很好地实现一个轮询CoroutineDispatcher的isActive属性的IdlingResource。但是,从调试情况来看,在检查此属性时,似乎从来没有活动的Job。

到目前为止,我已经尝试使用AsyncTask的THREAD_POOL_EXECUTOR进行内置空闲,但是当使用asCoroutineDispatcher扩展函数并使用生成的CoroutineDispatcher启动视图模型的作业时,它似乎不起作用。我曾尝试编写自定义的IdlingResource

ViewModel

代码语言:javascript
复制
fun authenticate(username: String, password: String) = viewModelScope.launch(Dispatchers.Default) {
    if (_authenticateRequest.value == true) {
        return@launch
    }

    _authenticateRequest.postValue(true)
    val res = loginRepo.authenticate(username, password)
    _authenticateRequest.postValue(false)

    when {
        res is Result.Success -> {
            _authenticateSuccess.postValue(res.item)
        }
        res is Result.Failure && res.statusCode.isHttpClientError -> {

            _authenticateFailure.postValue(R.string.invalid_password)
        }
        else -> {
            _authenticateFailure.postValue(R.string.network_error)
        }
    }
}

IdlingResource

代码语言:javascript
复制
class CoroutineDispatcherIdlingResource(
    private val resourceName: String,
    private val dispatcher: CoroutineDispatcher
) : IdlingResource {
    private var callback: IdlingResource.ResourceCallback? = null

    override fun getName() = resourceName

    override fun isIdleNow(): Boolean {
        if (dispatcher.isActive) { return false }

        callback?.onTransitionToIdle()
        return true
    }

    override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
        this.callback = callback
    }
}

Espresso测试

代码语言:javascript
复制
@RunWith(AndroidJUnit4::class)
class LoginIntegrationTest {
    @get:Rule
    val activityRule = ActivityTestRule(MainActivity::class.java)

    var idlingResource: CoroutineDispatcherIdlingResource? = null

    @Before
    fun before() {
        idlingResource = CoroutineDispatcherIdlingResource(this.javaClass.simpleName, Dispatchers.Default)
        IdlingRegistry.getInstance().register(idlingResource)
    }

    @Test
    fun loginFailure() {
        onView(withId(R.id.username))
            .perform(clearText()).perform(typeText("aslkdjqwe"))
        onView(withId(R.id.password))
            .perform(clearText()).perform(typeText("oxicjqwel"))
        onView(withId(R.id.login_button))
            .perform(click())

        onView(withId(com.google.android.material.R.id.snackbar_text))
            .check(matches(withText(R.string.invalid_password)))
    }
}

我期望一旦调用身份验证‘ViewModel’函数,isActive属性就会为true,但事实似乎并非如此。它总是看起来是假的,因为CoroutineDispatcher中从来没有活动的作业。

EN

回答 2

Stack Overflow用户

发布于 2019-06-17 11:46:37

想出一个解决方案!事实证明,AsyncTask的THREAD_POOL_EXECUTOR在这方面工作得很好。我错过的是一个用于Retrofit/OkHttp的IdlingResource。

我最初的假设是,在THREAD_POOL_EXECUTOR上运行的协程将在HTTP客户端关闭时被隐式地等待,但我已经使用IdlingResource here很好地完成了所有工作。

票数 2
EN

Stack Overflow用户

发布于 2019-06-14 02:44:16

CoroutineContext.isActive具有误导性,因为它检查上下文是否具有Job对象,以及该对象是否处于活动状态。CoroutineDispatcher是一个没有像Job这样的其他元素的上下文,所以它总是返回false

为了跟踪延续,您可能需要某种自定义ContinuationInterceptor来跟踪正在进行和已取消的延续。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56583557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档