OkHttp Idling Resource for Espresso

Handling asynchronism in Espresso

Chirag Kunder
InsideN26
3 min readJan 9, 2019

--

Graphics by R. Pais on base Photo by Carolyn V on Unsplash

If your Android app is doing a lot of network calls, Espresso tests can get flaky and handling asynchronism can get tricky. A common solution used is the Thread.sleep() which still doesn’t guarantee deterministic results. One way to solve this is by using Idling Resources.

Let’s consider this simple example which uses Retrofit and OkHttp to get user information from Github and display the name in a TextView.

Implementation

First we create an implementation for the API endpoint defined in the GithubService .

The OkHttp client is provided by OkHttpProvider which is a Singleton and the base url for Retrofit is provided by BaseUrlProvider. You will see the usages of these classes later in the tests.

We then get the user information for user octocat and display the login information in a TextView githubUserName . In case an error occurs it is displayed by an error message.

Testing

Note: For this example, I am using the androidx testing libraries.

First start a MockServer and create a fake response body which will be returned by the mock server.

We write a simple test which enqueues the mock response and checks if the correct user name is displayed in the TextView . A delay of 1 second is added to emulate a network call delay or some long running operations.

On running the shouldShowUserNameCorrectly test, it fails!

Why is the test failing?

The check() method loops the main thread until the app is idle.

What does idle mean in this context?

  1. There are no events in the main thread message queue.
  2. There are no tasks in the AsyncTask thread pool.
  3. All the registered idling resources are idle.

Since the network call is done asynchronously using enqueue , the UI thread is idle and Espresso does not know about the async network call happening in another thread. Hence it continues with the assertions leading to failure as the UI is not updated yet.

Solution

The solution is to tell Espresso to wait for long running operations and to do so we use the OkHttpIdlingResource (library from Jake Wharton), an IdlingResource for Espresso.

Note: Make sure you add android.useAndroidX=true and android.enableJetifier=true in the gradle.properties file since the OkHttpIdlingResource library uses the android support IdlingResource.

Creating test rule

Next we create a test rule for registering and unregistering IdlingResources with Espresso. OkHttpProvider provides the OkHttp instance used for Retrofit. If you are using Dagger, OkHttpProvider (also BaseUrlProvider) can be replaced with a Dagger module which provides the OkHttpClient. More information on testing with Dagger here.

Add rule to the test class

And voila! The tests pass!

Espresso waits for the IdlingResource to become idle i.e waits for the network call to complete and then continues with the assertions.

You can find the complete source code on Github.

Hope this helped. Happy testing! 🤓

References

  1. https://caster.io/courses/espresso
  2. https://caster.io/lessons/espresso-idling-resource-introduction

Interested in joining one of our teams as we grow?

If you’d like to join us on the journey of building the mobile bank the world loves to use, have a look at some of the Tech roles we’re looking for here.

Follow us on LinkedIn and Twitter to keep in touch with us!

--

--