IdlingResource, Dagger and Junit rules

Espresso has many challenges. One of them is writing IdlingResources

As you may know, using an IdlingResource is a way to tell Espresso to wait until your background threads are done before continuing testing. Espresso will pause until the IdlingResource says it’s idle.

I’m going to show an easy way of using IdlingResources with Junit @Rules. This will make your tests nicer and you’ll be able to reuse more code. We’re going to see two examples:

  1. IdlingResource for a thread pool
  2. IdlingResource for Okhttp

IdlingResource for a thread pool

If you use a thread pool to execute background tasks (which I recommend), this IdlingResource will wrap it to monitor if it’s busy. It will work with mostly all background tasks as long as you’re using the thread pool to execute them.

You’ll find the code for the IdlingResource in my sample project. Now that we have it, we’ll create a Junit rule (with dagger’s help):

public class ThreadPoolIdlingResourceRule implements TestRule {

private IdlingResource resource;

public ThreadPoolIdlingResourceRule() {
DemoApplicationComponent component = DemoApplication.getApplication().getComponent();
resource = new ThreadPoolIdlingResource("threadPoolExecutor", component.threadPoolExecutor());
}

@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Espresso.registerIdlingResources(resource);
base.evaluate();
Espresso.unregisterIdlingResources(resource);
}
};
}
}

I use dagger to get a hold of the thread pool executor instance used in my project. You can now use your Junit rule like this:

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class);
@Rule
public ThreadPoolIdlingResourceRule idlingResourceRule = new ThreadPoolIdlingResourceRule();


@Test
public void myTest() {
onView(withText(MainActivity.HELLO)).check(matches(isDisplayed()));
onView(withId(R.id.fab)).perform(click());
onView(withText(MainActivity.HELLO_WORLD)).check(matches(isDisplayed()));
}
}

You don’t need to register and unregister it, that’s already taken care of by the rule. Simple, isn’t it?

IdlingResource for Okhttp

In this example we’ll use Jake Whaton’s okhttp3-idling-resource library. To use it just add this to your gradle file

androidTestCompile 'com.jakewharton.espresso:okhttp3-idling-resource:1.0.0'

And now create your Junit rule:

public class IdlingResourceRule implements TestRule {

private IdlingResource resource;

public IdlingResourceRule() {
DemoApplicationComponent component = DemoApplication.getApplication().getComponent();
resource = OkHttp3IdlingResource.create("OkHttp", component.okHttpClient());
}

@Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Espresso.registerIdlingResources(resource);
base.evaluate();
Espresso.unregisterIdlingResources(resource);
}
};
}
}

And to use it in your Espresso test:

@Rule
public IdlingResourceRule idlingResourceRule = new IdlingResourceRule();

That’s it! Be aware that this last rule will only make Espresso wait during network calls. If you have any other non-UI and non-asyncTask code to be synced, Espresso might not wait for it.

Check out the source code in Github and happy testing!

And, if by any chance you’re interested in unit testing in Android, check this post!