Espresso does not wait until dialog is shown and fail

In some cases disable animations is not possible like:

  • when running tests on cloud devices. Firebase testlab doesn't allow changing the device configuration
  • when you are waiting for some background thread to update the user interface, like the an http response.

In those cases the simplest is to wait for an element to show. Here is how:

Simple helper:

class WaifForUIUpdate {

public static void waifForWithId(@IdRes int stringId) {
    
    ViewInteraction element;
    do {
        waitFor(500);

        //simple example using withText Matcher.
        element = onView(withText(stringId));

    } while (!MatcherExtension.exists(element));

}

static void waitFor(int ms) {
    final CountDownLatch signal = new CountDownLatch(1);

    try {
        signal.await(ms, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        Assert.fail(e.getMessage());
    }
}
}

Matcher from twisterrob

public class MatcherExtension {
 @CheckResult
    public static boolean exists(ViewInteraction interaction) {
        try {
            interaction.perform(new ViewAction() {
                @Override
                public Matcher<View> getConstraints() {
                    return any(View.class);
                }

                @Override
                public String getDescription() {
                    return "check for existence";
                }

                @Override
                public void perform(UiController uiController, View view) {
                    // no op, if this is run, then the execution will continue after .perform(...)
                }
            });
            return true;
        } catch (AmbiguousViewMatcherException ex) {
            // if there's any interaction later with the same matcher, that'll fail anyway
            return true; // we found more than one
        } catch (NoMatchingViewException ex) {
            return false;
        } catch (NoMatchingRootException ex) {
            // optional depending on what you think "exists" means
            return false;
        }
    }

}

Usage:

WaifForUIUpdate.waifForWithId(R.string.some_string);
//now do your validations

Finally it seems like the problem was animations. For make Espresso works properly is needed to disable animations in developer options menu.

Disable animations

In this case, the problem was solved. But there are other cases in which the problem could be a background task, like the comments to my question suggest. So I recommend to have a look at IdlingResource https://medium.com/azimolabs/wait-for-it-idlingresource-and-conditionwatcher-602055f32356#.pw55uipfj or this Espresso: Thread.sleep( );