In JavaScript (for example using Mocha) I can write asynchronous unit tests which assert things inside the final callback.
This is accomplished by passing a token function (usually called done
) as argument to the test method.
When the function is invoked, the testing framework understands that the test is completed.
For example:
it('succeeds or fails in the last callback', function(done) {
var deferred = Q.defer();
setTimeout(function() { deferred.resolve('expected'); }, 500);
deferred.promise.then(function(result) {
assertEquals('expected', result);
done(); // end of test
});
});
I see that Junit does not cater for such a scenario. First of all, test methods cannot handle an argument, and anyhow if I try for example:
@Test
public void testAssertionInsideContinuation() {
Long now = System.currentTimeMillis();
System.out.println("TimeMillis=" + now);
CompletableFuture fut = new CompletableFuture();
Executors.newScheduledThreadPool(1)
.schedule(() -> { fut.complete("whatever"); }, 500, TimeUnit.MILLISECONDS);
fut.thenRun(() -> {
long then = System.currentTimeMillis();
System.out.println("TimeMillis=" + then);
assertTrue(then - now >= 500);
});
}
the second println
will not be executed, because the test has happily completed long time before.
If I cheat and put a Thread.currentThread().sleep(500);
at the end of the test method, then the future gets a chance to be completed, and the assertion + the second printout are executed.
I have a few questions:
- what is the simplest Java setup in which I would be able to verify assertions inside callbacks/continuations/thenables (call them whatever you like) without having to block the test?
- do I have to give up Junit altogether?
- is there a mainstream testing framework (TestNG, maybe?) that allows writing async unit tests this way?
BTW, I'd also be grateful if anyone could suggest me a way to write this Java sample test without resorting to ScheduledFuture
's.
I have tried some experiment with supplyAsync
without really nailing down a solution.