How to make JUnit4 “Wait” for asynchronous job to finish before running tests

Issue

I am trying to write a test for my android app that communicates with a cloud service. Theoretically the flow for the test is supposed to be this:

  1. Send request to the server in a worker thread
  2. Wait for the response from the server
  3. Check the response returned by the server

I am trying to use Espresso’s IdlingResource class to accomplish that but it is not working as expected. Here’s what I have so far

My Test:

@RunWith(AndroidJUnit4.class)
public class CloudManagerTest {

FirebaseOperationIdlingResource mIdlingResource;

@Before
public void setup() {
    mIdlingResource  new FirebaseOperationIdlingResource();
    Espresso.registerIdlingResources(mIdlingResource);
}

@Test
public void testAsyncOperation() {
    Cloud.CLOUD_MANAGER.getDatabase().getCategories(new OperationResult<List<Category>>() {
        @Override
        public void onResult(boolean success, List<Category> result) {
            mIdlingResource.onOperationEnded();
            assertTrue(success);
            assertNotNull(result);
        }
    });
    mIdlingResource.onOperationStarted();
}
}

The FirebaseOperationIdlingResource

public class FirebaseOperationIdlingResource implements IdlingResource {

private boolean idleNow  true;
private ResourceCallback callback;


@Override
public String getName() {
    return String.valueOf(System.currentTimeMillis());
}

public void onOperationStarted() {
    idleNow  false;
}

public void onOperationEnded() {
    idleNow  true;
    if (callback ! null) {
        callback.onTransitionToIdle();
    }
}

@Override
public boolean isIdleNow() {
    synchronized (this) {
        return idleNow;
    }
}

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

When used with Espresso’s view matchers the test is executed properly, the activity waits and then check the result.

However plain JUNIT4 assert methods are ignored and JUnit is not waiting for my cloud operation to complete.

Is is possible that IdlingResource only work with Espresso methods ? Or am I doing something wrong ?

Solution

I use Awaitility for something like that.

It has a very good guide, here is the basic idea:

Wherever you need to wait:

await().until(newUserIsAdded());

elsewhere:

private Callable<Boolean> newUserIsAdded() {
      return new Callable<Boolean>() {
            public Boolean call() throws Exception {
                  return userRepository.size()  1; // The condition that must be fulfilled
            }
      };
}

I think this example is pretty similar to what you’re doing, so save the result of your asynchronous operation to a field, and check it in the call() method.

Answered By – nasch

Leave a Comment