J'ai un test JUnit que je souhaite faire attendre pendant un certain 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 cela lève une exception IllegalMonitorStateException (comme prévu). Y a-t-il une astuce ou ai-je besoin d'un autre moniteur?
java
junit
thread-safety
Kylar
la source
la source
Thread.sleep
dire quelque chose comme Utiliser Thread.sleep dans un test est généralement une mauvaise idée. Il crée des tests fragiles qui peuvent échouer de manière imprévisible en fonction de l'environnement ("Passe sur ma machine!") Ou de la charge. Ne vous fiez pas au timing (utilisez des simulations) ou n'utilisez pas de bibliothèques telles que Awaitility pour les tests asynchrones.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 tout ce que vous attendez s'est réellement produit.
Si vous attendez une demande de repos, par exemple, elle revient peut-être généralement dans 5 secondes, mais si vous définissez votre sommeil sur 5 secondes le jour où votre demande reviendra dans 10 secondes, votre test échouera.
Pour remédier à cela, JayWay a un excellent utilitaire appelé Awatility qui est parfait pour s'assurer qu'une condition spécifique se produit avant de passer à autre chose.
Il a également une belle api fluide
https://github.com/jayway/awaitility
la source
Si votre analyseur de code statique (comme SonarQube) se plaint, mais que vous ne pouvez pas penser à une autre façon, plutôt que de dormir, vous pouvez essayer avec un hack comme:
Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);
C'est conceptuellement incorrect, mais c'est la même chose queThread.sleep(1000)
.Le meilleur moyen, bien sûr, est de passer un Callable, avec votre condition appropriée, plutôt que
true
ce que j'ai.https://github.com/awaitility/awaitility
la source
Duration
classe, mais depuis la version 4, ils l'ont renomméeDurations
.Vous pouvez utiliser la bibliothèque java.util.concurrent.TimeUnit qui utilise Thread.sleep en interne. La syntaxe devrait ressembler à ceci:
Cette bibliothèque fournit une interprétation plus claire de l'unité de temps. Vous pouvez utiliser «HEURES» / «MINUTES» / «SECONDES».
la source
sleep()
affecte-t-il le thread de travail?Vous pouvez également utiliser l'
CountDownLatch
objet comme expliqué ici .la source
Il y a un problème général: il est difficile de se moquer du temps. En outre, il est très mauvais de placer du code à exécution / attente longue dans un test unitaire.
Donc, pour rendre une API de planification testable, j'ai utilisé une interface avec une implémentation réelle et fictive comme celle-ci:
Avec cela, vous pouvez imiter le temps dans votre test:
Une simulation multi-threading avancée
Clock
est bien sûr beaucoup plus complexe, mais vous pouvez la créer avec desThreadLocal
références et une bonne stratégie de synchronisation de l'heure, par exemple.la source