数据绑定导致Espresso测试失败 [英] Espresso test fails due to Data binding

查看:63
本文介绍了数据绑定导致Espresso测试失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的viewmodel类:

This is my viewmodel class :

class MainViewModel(
    private val schedulerProvider: BaseSchedulerProvider,
    private val api : StorytelService
) : BaseViewModel() {

    private val _posts = MutableLiveData<List<Post>>()
    val posts: LiveData<List<Post>>
        get() = _posts

    private val _status = MutableLiveData<Status>()
    val status: LiveData<Status>
        get() = _status

    init {
        showPhotos()
    }

    fun showPhotos() {
        EspressoIdlingResource.increment() // App is busy until further notice
        _status.postValue(Status.LOADING)
        compositeDisposable.add(api.getPhotos()
            .subscribeOn(schedulerProvider.io())
            .observeOn(schedulerProvider.ui())
            .doFinally {
                if (!EspressoIdlingResource.countingIdlingResource.isIdleNow) {
                    EspressoIdlingResource.decrement() // Set app as idle.
                }
            }
            .subscribe({
                _status.postValue(Status.SUCCESS)
                showPosts(it)
            }) {
                _status.postValue(Status.ERROR)
                Timber.e(it)
            })
    }

    private fun showPosts(networkPhotos: List<NetworkPhoto>) {
        EspressoIdlingResource.increment() // App is busy until further notice
        _status.postValue(Status.LOADING)
        compositeDisposable.add(api.getPosts()
            .subscribeOn(schedulerProvider.io())
            .observeOn(schedulerProvider.ui())
            .doFinally {
                if (!EspressoIdlingResource.countingIdlingResource.isIdleNow) {
                    EspressoIdlingResource.decrement() // Set app as idle.
                }
            }
            .subscribe({ networkPosts ->
                _status.postValue(Status.SUCCESS)
                _posts.postValue(
                    PostAndImages(networkPosts, networkPhotos).asDomaineModel()
                )
            }) {
                _status.postValue(Status.ERROR)
                Timber.e(it)
            })
    }

这是我的recyclerView布局:

This is my recyclerView in layout :

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            app:showData="@{vm.status}"
            tools:listitem="@layout/post_item" />

这是绑定适配器:

@BindingAdapter("showData")
fun View.showData(status: Status) {
    visibility = if (status == Status.SUCCESS) View.VISIBLE else View.GONE
}

您注意到我正在使用EspressoIdlingResource,但是当我按照espresso测试运行时,它失败了:

As you notice I am using EspressoIdlingResource, but when I run following espresso test, it fails :

    @Test
    fun shouldBeAbleToLoadList() {
        onView(withId(R.id.recycler_view)).check(matches(isDisplayed()))
    } 

如果在测试开始时添加Thread.sleep(5000),它将起作用.如何解决?

If I add Thread.sleep(5000) in the beginning of the test, it works. How to resolve it?

推荐答案

使用Idling Resource应该可以,但是它们有些乏味.

It should be possible with Idling Resource however they are a little bit tedious.

我刚刚更新了旧的viewMatcher代码:

I've just updated an old viewMatcher code:

/**
 * Perform action of waiting for a specific view id to be displayed.
 * @param viewId The id of the view to wait for.
 * @param millis The timeout of until when to wait for.
 */
public static ViewAction waitDisplayed(final int viewId, final long millis) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isRoot();
        }

        @Override
        public String getDescription() {
            return "wait for a specific view with id <" + viewId + "> has been displayed during " + millis + " millis.";
        }

        @Override
        public void perform(final UiController uiController, final View view) {
            uiController.loopMainThreadUntilIdle();
            final long startTime = System.currentTimeMillis();
            final long endTime = startTime + millis;
            final Matcher<View> matchId = withId(viewId);
            final Matcher<View> matchDisplayed = isDisplayed();

            do {
                for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
                    if (matchId.matches(child) && matchDisplayed.matches(child)) {
                        return;
                    }
                }

                uiController.loopMainThreadForAtLeast(50);
            }
            while (System.currentTimeMillis() < endTime);

            // timeout happens
            throw new PerformException.Builder()
                    .withActionDescription(this.getDescription())
                    .withViewDescription(HumanReadables.describe(view))
                    .withCause(new TimeoutException())
                    .build();
        }
    };
}

那你只应该做:

@Test
    fun shouldBeAbleToLoadList() {
        onView(isRoot()).perform(waitDisplayed(R.id.recycler_view, 5000));
    } 

5000的超时时间为5秒(5000毫秒),您可以根据需要进行更改.

the 5000 is a timeout of 5 secs (5000 millis), you can change it if you want to.

执行waitDisplayed后,可能会显示该元素或已达到超时.在最后一种情况下,将抛出Exception.

After waitDisplayed is executed it could happen that the element is shown or the timeout has been reached. In the last case an Exception will be thrown.

这篇关于数据绑定导致Espresso测试失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆