1
    AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    builder.setMessage(message)
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    login(activity);
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {

                    dialog.cancel();
                    activity.finish();
                }
            });
    AlertDialog alert = builder.create(); // Crash
    alert.show();

The app runs fine and shows the alert dialog when I run it normally, but when I run it in an instrumented test, it crashes in builder.create at the first line:

        final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);

with this exception:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

This closes the app and then the test fails because there isn't any activity:

android.support.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?

This is a thread problem, but that's not what I expected based on an answer here:

To verify if dialog appears you can simply check if View with a text that present inside the dialog is shown:

onView(withText("dialogText")).check(matches(isDisplayed()));

I don't understand how I'm supposed to check if the text is displayed if the app crashes before the dialog is created.

EDIT:

    mActivityRule.launchActivity(intent);

    mActivityRule.getActivity().showOptionDialog();

    onView(withText(mActivityRule.getActivity().getString(R.string.dialogText))).check(matches(isDisplayed()));
Community
  • 1
  • 1
Questioner
  • 2,451
  • 4
  • 29
  • 50

1 Answers1

0

A couple things that will likely help you...

  1. Calling mActivityRule.getActivity().showOptionDialog(); in an Espresso test is not the 'Espresso' way. Unless your test is properly annotated, it's not running on the UI Thread, so this is a case where you are calling something that should be done on the UI Thread from the Instrumentation Thread. You can get around this by doing something like:

    rule.runOnUiThread(new Runnable() { @Override public void run() { mActivityRule.getActivity().showOptionDialog(); } });

Doing this may require you to build out your own synchronization logic to make sure that future Espresso statements are not run before this occurs.

The better way to test this using Espresso is to use an onView(XXX).perform(click()) on the UI control that would normally invoke showOptionsDialog().

  1. Additionally, you don't need to resolve the string that you pass to withText() yourself, you can just use the string resource id, but this isn't the cause of the issue that you are seeing.
jdonmoyer
  • 1,245
  • 1
  • 18
  • 28
  • Thanks, but showOptionsDialog() is not triggered from the click of a button. It's triggered after a certain HTTP response. – Questioner Jun 08 '17 at 15:04
  • @Questioner then you will need to use one of the various mechanisms that Espresso provides for running that method on the UIThread. – jdonmoyer Jun 08 '17 at 15:20
  • @jdonmoyer I have a bit similar issue can you please help with this https://stackoverflow.com/questions/63793127/alertdialog-is-not-getting-launched-properlydistorting-app-ui-when-i-am-trying – sak Sep 08 '20 at 11:57