How to use JUnit to test asynchronous processes
An alternative is to use the CountDownLatch class.
public class DatabaseTest { /** * Data limit */ private static final int DATA_LIMIT = 5; /** * Countdown latch */ private CountDownLatch lock = new CountDownLatch(1); /** * Received data */ private List<Data> receiveddata; @Test public void testDataRetrieval() throws Exception { Database db = new MockDatabaseImpl(); db.getData(DATA_LIMIT, new DataCallback() { @Override public void onSuccess(List<Data> data) { receiveddata = data; lock.countDown(); } }); lock.await(2000, TimeUnit.MILLISECONDS); assertNotNull(receiveddata); assertEquals(DATA_LIMIT, receiveddata.size()); }}
NOTE you can't just used syncronized with a regular object as a lock, as fast callbacks can release the lock before the lock's wait method is called. See this blog post by Joe Walnes.
EDIT Removed syncronized blocks around CountDownLatch thanks to comments from @jtahlborn and @Ring
You can try using the Awaitility library. It makes it easy to test the systems you're talking about.
If you use a CompletableFuture (introduced in Java 8) or a SettableFuture (from Google Guava), you can make your test finish as soon as it's done, rather than waiting a pre-set amount of time. Your test would look something like this:
CompletableFuture<String> future = new CompletableFuture<>();executorService.submit(new Runnable() { @Override public void run() { future.complete("Hello World!"); }});assertEquals("Hello World!", future.get());