Я пытаюсь найти способ красиво реализовать IdlingResource, который будет опрашивать свойство CoroutineDispatcher isActive
. Однако из-за отладки при проверке этого свойства никогда не появляется активное задание.
До сих пор я пытался использовать THREAD_POOL_EXECUTOR
от AsyncTask для встроенного холостого хода, но, похоже, он не работает при использовании функции расширения asCoroutineDispatcher
и использовании этого результата CoroutineDispatcher
для запуска задания ViewModel. Я попытался написать собственный 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
}
}
Эспрессо-тест
@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)))
}
}
Я ожидаю, что свойство isActive
станет истинным после вызова функции authenticate ViewModel, но, похоже, это не так. Это всегда выглядит как ложь, так как в CoroutineDispatcher никогда не бывает активного задания.