Une méthode que j'ai trouvé très utile pour tester des méthodes asynchrones est l'injection d'un Executor
de l'instance de l'objet-test du constructeur. Dans la production, l'exécuteur testamentaire de l'instance est configuré pour s'exécuter de manière asynchrone alors que dans le test, il peut être une fantaisie à exécuter de manière synchrone.
Supposons donc que je suis en train de tester la méthode asynchrone Foo#doAsync(Callback c)
,
class Foo {
private final Executor executor;
public Foo(Executor executor) {
this.executor = executor;
}
public void doAsync(Callback c) {
executor.execute(new Runnable() {
@Override public void run() {
// Do stuff here
c.onComplete(data);
}
});
}
}
Dans la production, je voudrais construire Foo
avec un Executors.newSingleThreadExecutor()
Exécuteur exemple, pendant le test, je serais probablement le construire avec un synchrones liquidateur qui procède de la façon suivante --
class SynchronousExecutor implements Executor {
@Override public void execute(Runnable r) {
r.run();
}
}
Maintenant, mon JUnit test de la méthode asynchrone est très propre
@Test public void testDoAsync() {
Executor executor = new SynchronousExecutor();
Foo objectToTest = new Foo(executor);
Callback callback = mock(Callback.class);
objectToTest.doAsync(callback);
// Verify that Callback#onComplete was called using Mockito.
verify(callback).onComplete(any(Data.class));
// Assert that we got back the data that we expected.
assertEquals(expectedData, callback.getData());
}