1

I have:

        onView(withId(R.id.login_email_textview)).perform(clearText(), closeSoftKeyboard());
        onView(withId(R.id.password_edittext)).perform(clearText(), closeSoftKeyboard());
        onView(withId(R.id.login_email_textview)).perform(typeText(email), closeSoftKeyboard());
        onView(withId(R.id.password_edittext)).perform(typeText(password), closeSoftKeyboard());
        onView(withId(R.id.email_sign_in_button)).perform(click());
        intended(hasComponent(new ComponentName(getTargetContext(), MainActivity.class)));

After the login button is pressed a Loading dialog shows up and Async task calls the server to check the credentials. After response the LoginActivity, witch I'm testing called finish() and MainActivity is started.

The test hangs after the login button is pressed. Also using:

@Rule
public IntentsTestRule<LoginActivity> mActivityRule = new IntentsTestRule<>(LoginActivity.class);

Also in my code after I/m calling startActivity(), I'm calling finish() on the LoginActivity.

On sign_in_button I'm calling Volley request.

SpyZip
  • 5,511
  • 4
  • 32
  • 53

2 Answers2

1

How to fix your issue

I assume, that the LoadingDialog is showing an animated ProgressBar.

Using a ProgressBar and Volley together is actually not a bad idea. The ProgressBar will force Espresso to wait until Volley has finished its work in the background.

I assume, that your tests "hang" because you do not dismiss the LoadingDialog. So, to fix the issue, dismiss the LoadingDialog when you receive the response from Volley. But do not use Espresso to dismiss the LoadingDialog.

More Information

There are "known issues" when using ProgressBar and Volley individually:

Issues with ProgressBar

If the LoadingDialog shows an animated ProgressBar, the animation blocks Espresso. The animation keeps the app's main thread busy and Espresso waits until it times out.

See here for workarounds

Issues with Volley

Espresso does not know about Volley. If Volley executes requests in a background thread (I hope it does), Espresso does not wait, and your test will probably end before Volley returns a response.

An IdlingResource can be used to make Espresso wait for anything.

Community
  • 1
  • 1
thaussma
  • 9,756
  • 5
  • 44
  • 46
  • I'll implement custom IdlingResource to wait for the Volley request to finish. – SpyZip Feb 21 '17 at 11:08
  • I made Espresso wait with IdelingResource, but when it clicks to start the new activity it hangs. If I manually go back to the previous activity the test continues – SpyZip Feb 24 '17 at 14:52
  • Yes. Do you still have the ProgressDialog? And does it show a indeterminate ProgressBar? – thaussma Feb 24 '17 at 15:30
  • No I removed it. I narrowed the problem to VolleyIdlingResource being lost after the transition to the second Activity. – SpyZip Feb 24 '17 at 15:31
0

So this is the solution I came up with:

Custom IdlingResource:

public class VolleyIdlingResource implements IdlingResource {
private static final String TAG = "VolleyIdlingResource";
private final String resourceName;

// written from main thread, read from any thread.
private volatile ResourceCallback resourceCallback;

private Field requests;
private RequestQueue requestQueue;

public VolleyIdlingResource(String resourceName, Context context) throws SecurityException, NoSuchFieldException {
    this.resourceName = checkNotNull(resourceName);

    requestQueue = MyApplication.get(context).getRequestQueue();

    requests = RequestQueue.class.getDeclaredField("requests");
    requests.setAccessible(true);
}

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

@Override
public boolean isIdleNow() {
    try {
        Set<Request> set = (Set<Request>) requests.get(requestQueue);
        int count = set.size();
        if (set != null) {

            if (count == 0) {
                resourceCallback.onTransitionToIdle();
            } else {
            }
            return count == 0;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return true;
}

@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
    this.resourceCallback = resourceCallback;
} 
}

And then in the test:

VolleyIdlingResource volleyResources;
        try {
            volleyResources = new VolleyIdlingResource("VolleyCalls", mActivityRule.getActivity());
            registerIdlingResources(volleyResources);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        intended(hasComponent(new ComponentName(getTargetContext(), MainActivity.class)));

Based on https://github.com/bolhoso/espresso-volley-tests/blob/master/EspressoTest/src/com/example/espressovolley/test/MyTest.java

SpyZip
  • 5,511
  • 4
  • 32
  • 53