140 votes

Comment faire attendre un test JUnit ?

J'ai un test JUnit que je veux faire attendre pendant une période de temps de manière synchrone. Mon test JUnit ressemble à ceci :

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);
    // WAIT FOR 2 SECONDS
    assertNull(sco.getIfNotExipred("foo"));
}

J'ai essayé Thread.currentThread().wait() mais le système génère un IllegalMonitorStateException (comme prévu).

Y a-t-il une astuce ou ai-je besoin d'un autre écran ?

129voto

Muel Points 4030

Et si Thread.sleep(2000); ? :)

117voto

Ben Glasser Points 466

Thread.sleep() pourrait fonctionner dans la plupart des cas, mais généralement, si vous attendez, vous attendez en fait qu'une condition ou un état particulier se produise. Thread.sleep() ne garantit pas que ce que vous attendez s'est effectivement produit.

Si vous attendez une demande de repos, par exemple, qui est généralement renvoyée en 5 secondes, mais si vous réglez votre sommeil sur 5 secondes le jour où votre demande est renvoyée en 10 secondes, votre test va échouer.

Pour remédier à cela, JayWay propose un excellent utilitaire appelé Awatility ce qui est parfait pour s'assurer qu'une condition spécifique se produit avant de passer à autre chose.

Il dispose également d'une interface utilisateur conviviale.

await().until(() -> 
{
    return yourConditionIsMet();
});  

https://github.com/jayway/awaitility

40voto

rastaman Points 387

Si votre analyseur de code statique (comme SonarQube) se plaint, mais que vous ne trouvez pas d'autre solution, plutôt que de dormir, vous pouvez essayer avec un hack du genre : Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true); C'est conceptuellement incorrect, mais c'est la même chose que Thread.sleep(1000) .

La meilleure façon, bien sûr, est de passer un Callable, avec votre condition appropriée, plutôt que true que j'ai.

https://github.com/awaitility/awaitility

30voto

Akshay Pagar Points 297

Vous pouvez utiliser la bibliothèque java.util.concurrent.TimeUnit qui utilise en interne Thread.sleep. La syntaxe devrait ressembler à ceci :

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);

    TimeUnit.MINUTES.sleep(2);

    assertNull(sco.getIfNotExipred("foo"));
}

Cette bibliothèque fournit une interprétation plus claire de l'unité de temps. Vous pouvez utiliser 'HOURS'/'MINUTES'/'SECONDS'.

20voto

pirho Points 5491

S'il est absolument nécessaire de générer un délai dans un test CountDownLatch est une solution simple. Dans votre classe de test, déclarez :

private final CountDownLatch waiter = new CountDownLatch(1);

et dans le test si nécessaire :

waiter.await(1000 * 1000, TimeUnit.NANOSECONDS); // 1ms

Il n'est peut-être pas nécessaire de le dire, mais il faut garder à l'esprit que les temps d'attente doivent être réduits et ne pas cumuler les attentes à trop d'endroits.

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