246 votes

Comment utiliser Junit pour tester le processus asynchrones

Comment Testez-vous méthodes qui déclenchent des processus asynchrones avec Junit ?

Je ne sais pas comment faire mon test à attendre que le processus à la fin (ce n’est pas exactement un test unitaire, c’est plus comme un critère d’intégration car il implique plusieurs classes et pas un seul)

220voto

Strawberry Points 3323

Une alternative est d'utiliser le CountDownLatch classe.

public class DatabaseTest
{

/** Data limit */
private static 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());
}

}

REMARQUE vous ne pouvez pas simplement utilisé synchronisé avec un objet normal qu'un verrou, aussi vite rappels peuvent libérer le verrou avant de la serrure attendre méthode est appelée. Voir ce post de blog de Joe Walnes.

EDIT Retiré synchronisées blocs autour de CountDownLatch grâce à des commentaires de @jtahlborn et @Anneau

87voto

Johan Points 1120

Vous pouvez essayer d’utiliser le cadre de Awaitility . Il est facile de tester les systèmes que vous parlez.

52voto

Cem Catikkas Points 4986

À mon humble avis c'est une mauvaise pratique d'avoir des tests unitaires de créer ou d'attendre sur les threads, etc. Vous souhaitez ces tests à exécuter, dans des fractions de secondes. C'est pourquoi je voudrais proposer un 2-étapes de l'approche de test async processus.

  1. Test de votre async processus est soumis correctement. Vous pouvez vous moquer de l'objet qui accepte vos demandes asynchrones et assurez-vous que le travail a soumis propriétés correctes, etc.
  2. Test de votre async rappels sont en train de faire les bonnes choses. Ici, vous pouvez vous moquer de la soumis à l'origine de l'emploi et supposons qu'elle est correctement initialisé et vérifiez que vos rappels sont corrects.

23voto

Commencez le processus et d’attendre le résultat, en utilisant un `` .

21voto

Matthew Points 1650

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());
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X