我正在尝试找到一种方法来很好地实现一个轮询CoroutineDispatcher的isActive
属性的IdlingResource。但是,从调试情况来看,在检查此属性时,似乎从来没有活动的Job。
到目前为止,我已经尝试使用AsyncTask的THREAD_POOL_EXECUTOR
进行内置空闲,但是当使用asCoroutineDispatcher
扩展函数并使用生成的CoroutineDispatcher
启动视图模型的作业时,它似乎不起作用。我曾尝试编写自定义的IdlingResource
ViewModel
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
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测试
@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中从来没有活动的作业。
发布于 2019-06-17 11:46:37
想出一个解决方案!事实证明,AsyncTask的THREAD_POOL_EXECUTOR在这方面工作得很好。我错过的是一个用于Retrofit/OkHttp的IdlingResource。
我最初的假设是,在THREAD_POOL_EXECUTOR上运行的协程将在HTTP客户端关闭时被隐式地等待,但我已经使用IdlingResource here很好地完成了所有工作。
发布于 2019-06-14 02:44:16
CoroutineContext.isActive
具有误导性,因为它检查上下文是否具有Job
对象,以及该对象是否处于活动状态。CoroutineDispatcher
是一个没有像Job
这样的其他元素的上下文,所以它总是返回false
。
为了跟踪延续,您可能需要某种自定义ContinuationInterceptor
来跟踪正在进行和已取消的延续。
https://stackoverflow.com/questions/56583557
复制相似问题