Testing endless scrolling RecyclerView with Espresso and RxJava Testing endless scrolling RecyclerView with Espresso and RxJava android android

Testing endless scrolling RecyclerView with Espresso and RxJava


I spend some time and fixed your test. Hope it will help you.

1.You are generating the test data in a wrong way. In makeInstaItem you pass as i indexes (and so 0 value) so the last item in the list has the same created time (0L) as progress item created by InstaAdapter.:

private static InstaItem makeInstaItem(String prefix, int i, int dateСoefficient) {    InstaItem item = new InstaItem();    item.setLocation(new Location(prefix + "_location_" + i));    item.setCreatedTime(i * 1000000L * dateСoefficient);    item.setImages(makeInstaImages());    item.setId(randomUuid());    return item;}

This should be changed to for example:

private static InstaItem makeInstaItem(String prefix, int i, int dateСoefficient) {    InstaItem item = new InstaItem();    item.setLocation(new Location(prefix + "_location_" + i));    item.setCreatedTime((i + 1) * 1000000L * dateСoefficient);    item.setImages(makeInstaImages());    item.setId(randomUuid());    return item;}

Created test list is passed as reference to your adapter. After progress item is added it is one before last item. In tests you are trying to match this progress bar item like it would be regular location item, because of this it crashes. After all my changes its is added as last item and removed before loop in test reaches it.

2.In InstaPresenter you are not adding items when loadMore subscription is called:

subscribe(x -> {    Timber.d("load more - items fetched");}

Change to for example:

subscribe(items -> {    if (!items.isEmpty()) {        getMvpView().showFeed(items);    }    Timber.d("load more - items fetched");}

3.You don't need delay at all. Keep implementation simple as for example:

when(mockDataManager.getOldFeedItemsFromServer()).thenReturn(Observable.just(oldFeed.getInstaItems())            .observeOn(AndroidSchedulers.mainThread())            .doOnNext(x -> {                Timber.d("On next after delay");                when(mockDataManager.subscribeOnFeedItemsChanges())                        .thenReturn(Observable.just(oldFeed.getInstaItems()));            }));instaActivityActivityTestRule.launchActivity(null);int position = 0;for (InstaItem item : feed.getInstaItems()) {    onView(withId(R.id.recycler_view))                .perform(RecyclerViewActions.scrollToPosition(position));    onView(withText(item.getLocation().getName()))                .check(matches(isDisplayed()));    onView(withText(InstaAdapter.dateFormat.format(new Date(item.getCreatedTime() * 1000))))                .check(matches(isDisplayed()));    position++;}for (InstaItem item : oldFeed.getInstaItems()) {    onView(withId(R.id.recycler_view))                .perform(RecyclerViewActions.scrollToPosition(position));    onView(withText(item.getLocation().getName()))                .check(matches(isDisplayed()));    onView(withText(InstaAdapter.dateFormat.format(new Date(item.getCreatedTime() * 1000))))                .check(matches(isDisplayed()));    position++;}
  1. Just my small personal suggestion. I would rather test presenter logic with unit tests than struggle with UI testing.

I recorded the video to show how it works after above changes


The referenced project no longer builds with recent versions of Android Studio and JDK 11.

When using Espresso with RxJava, you can use https://github.com/square/RxIdler to register the needed IdlingResources and wrap any custom Rx schedulers.