Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 ?

like image 883
Charles-Eugene Loubao Avatar asked Dec 19 '22 17:12

Charles-Eugene Loubao


1 Answers

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.

like image 59
nasch Avatar answered Dec 21 '22 07:12

nasch