Why is androidx espresso .check() causing androidx.test.espresso.IdlingResourceTimeoutException

I have some unit tests using androidx Espresso Every time I run the test I get the following error.

androidx.test.espresso.IdlingResourceTimeoutException: Wait for [WorkTrackerIdlingResource] to become idle timed out

Why am I getting timed out?

Its timing out on this line of code in my unittests, onView(withId(R.id.map_container)).check(matches(isDisplayed()));

Unit Test Class:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class CanvassFragmentTest extends TopLevelNavFragmentTest<CanvassFragment> {
    @NonNull
    @Override
    protected TopLevelNavFragment getTargetTopLevelNavFragment(@NonNull MainActivity activity) {
        return activity.mCanvassFragment;
    }

    @Test
    public void mapContainer_isDisplayed() {
        onView(withId(R.id.id1_container)).check(matches(isDisplayed()));
    }


}

And the xml which has the view we are trying to test.

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.company.MapContainerFragment">

    <FrameLayout
        android:id="@+id/id1_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

   .....
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

I've tried changing the idlepreferences so that the timeout is 5 minutes and I still get the error.

EDIT 1

as request I'm adding the code were I add onTransitionToIdle at the bottom of this class bellow

public class WaitForWorkRule implements TestRule {

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                WorkTrackerIdlingResource idler = new WorkTrackerIdlingResource();
                //Espresso.registerIdlingResources(idler);
                IdlingRegistry.getInstance().register(idler);
                try {
                    base.evaluate();
                } finally {
                    IdlingRegistry.getInstance().unregister(idler);
                }
            }
        };
    }

    /**
     * @hide visible for injection
     */
    public static class WorkTrackerIdlingResource implements IdlingResource {

        private static final String TAG = WorkTrackerIdlingResource.class.getSimpleName();

        @Inject
        WorkTracker mWorkTracker;

        @Nullable
        ResourceCallback mResourceCallback;

        public WorkTrackerIdlingResource() {
            getUiTestInjector().inject(this);
        }

        @Override
        public String getName() {
            return TAG;
        }

        @Override
        public boolean isIdleNow() {
            boolean idle = !mWorkTracker.isAnyoneWorking();
            if (idle && mResourceCallback != null) mResourceCallback.onTransitionToIdle();
            return idle;
        }

        @Override
        public void registerIdleTransitionCallback(@Nullable ResourceCallback callback) {
            mResourceCallback = callback;
        }
    }
}

And this is the code were we register it as a rule.

    @Rule
    public final RuleChain mRuleChain;

    public UiTest(@NonNull Class<T> activityClass) {
    mActivityTestRule = new ActivityTestRule<>(activityClass);
    mRuleChain = createRuleChain();
}



@NonNull
private RuleChain createRuleChain() {
    RuleChain chain = RuleChain.emptyRuleChain()
            .around(new InjectionRule())
            .around(new WaitForWorkRule());

    if (loggedIn()) {
        chain = chain.around(new LoggedInRule());
    }

    return chain.around(mActivityTestRule);
}

1 answer

  • answered 2018-11-08 20:30 Aaron

    Here's a brief explanation why your test always time out: you set a test rule that registers an idling resource before test begins, then when your activity starts, the main thread becomes busy. Generally, the test will continue when the main thread becomes idle, but your idling resource now blocks it and does not call onTransitionToIdle. So no matter how much time you set, it will always time out.

    I think your usage of idling resource here may be not useful or incorrect. If there's no use case for it, you can take the rule out and it should work fine.