Is it possible to disable Toasts or wait until toast disappears while testing

只愿长相守 提交于 2019-12-01 04:47:59

You can let Espresso wait until all toasts are disappeared with a custom idling resource.

Here I use CountingIdlingResource which is a idling resource managing a counter: when the counter changes from non-zero to zero it notifies the transition callback.

Here is a complete example; the key points follow:

public final class ToastManager {
    private static final CountingIdlingResource idlingResource = new CountingIdlingResource("toast");
    private static final View.OnAttachStateChangeListener listener = new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(final View v) {
            idlingResource.increment();
        }

        @Override
        public void onViewDetachedFromWindow(final View v) {
            idlingResource.decrement();
        }
    };

    private ToastManager() { }

    public static Toast makeText(final Context context, final CharSequence text, final int duration) {
        Toast t = Toast.makeText(context, text, duration);
        t.getView().addOnAttachStateChangeListener(listener);
        return t;
    }

    // For testing
    public static IdlingResource getIdlingResource() {
        return idlingResource;
    }
}

How to show the toast:

ToastManager.makeText(this, "Third", Toast.LENGTH_SHORT).show();

How to set-up/tear-down a test:

@Before
public void setUp() throws Exception {
    super.setUp();
    injectInstrumentation(InstrumentationRegistry.getInstrumentation());
    Espresso.registerIdlingResources(ToastManager.getIdlingResource());
    getActivity();
}

@After
public void tearDown() throws Exception {
    super.tearDown();
    Espresso.unregisterIdlingResources(ToastManager.getIdlingResource());
}

I have not found any perfect solution to this, but the best is to make a mToast member variable visible for testing, and use that to cancel any active toast in @After, like this:

When showing toast (the production code for the Activity under test):

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
Toast mToast;

private void showToast(final String text) {
    mToast = Toast.makeText(this, text, Toast.LENGTH_LONG);
    mToast.show();
}

The test code (in the same package as the code under test):

    @After
    public void tearDown() {
        // Remove any toast message that is still shown:
        Toast toast = mActivityRule.getActivity().mToast;
        if (toast != null) {
            toast.cancel();
        }
    }

This will require you to change the production code a tiny bit, but using @VisibleForTesting in the latest version of Android Studio will give error if you use the member variable elsewhere.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!