Согласно вашим журналам ошибок RecyclerView{..., child-count=0}
, похоже, что ваше представление загружает данные асинхронно, и действие представления повторного вызова вызывается слишком рано. Самый простой способ исправить это, просто позвонив Thread.sleep(...)
перед действием.
В качестве альтернативы вы можете использовать IdlingResource
от Espresso в вашем тестовом примере:
fun waitUntil(matcher: Matcher<View>): ViewAction = object : ViewAction {
override fun getConstraints(): Matcher<View> {
return any(View::class.java)
}
override fun getDescription(): String {
return StringDescription().let {
matcher.describeTo(it)
"wait until: $it"
}
}
override fun perform(uiController: UiController, view: View) {
if (!matcher.matches(view)) {
ViewPropertyChangeCallback(matcher, view).run {
try {
IdlingRegistry.getInstance().register(this)
view.viewTreeObserver.addOnDrawListener(this)
uiController.loopMainThreadUntilIdle()
} finally {
view.viewTreeObserver.removeOnDrawListener(this)
IdlingRegistry.getInstance().unregister(this)
}
}
}
}
}
Далее вам нужно создайте пользовательское сопоставление RecyclerView
, чтобы проверить, пусто ли оно:
fun hasItemCount(itemCount: Matcher<Int>): Matcher<View> {
return object : BoundedMatcher<View, RecyclerView>(RecyclerView::class.java) {
override fun describeTo(description: Description) {
description.appendText("has item count: ")
itemCount.describeTo(description)
}
override fun matchesSafely(view: RecyclerView): Boolean {
return view.adapter?.let {
itemCount.matches(it.itemCount)
} ?: false
}
}
}
Затем вы можете использовать действие и сопоставитель, чтобы подождать, пока ваш RecyclerView
заполнится или будет готов:
onView(withId(R.id.recyclerView)).perform(
waitUntil(hasItemCount(greaterThan(0))),
RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(17)
)