OkHttp Idling Resource for Espresso
Handling asynchronism in Espresso
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?
- There are no events in the main thread message queue.
- There are no tasks in the
AsyncTask
thread pool. - 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
andandroid.enableJetifier=true
in thegradle.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
@get:Rule
var rule = OkHttpIdlingResourceRule()
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
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.