Ich habe einen JUnit-Test, auf den ich synchron einige Zeit warten möchte. Mein JUnit-Test sieht folgendermaßen aus:
@Test
public void testExipres(){
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
//WAIT FOR 2 SECONDS
assertNull(sco.getIfNotExipred("foo"));
}
Ich habe Thread.currentThread (). Wait () ausprobiert, aber es wird eine IllegalMonitorStateException ausgelöst (wie erwartet). Gibt es einen Trick oder brauche ich einen anderen Monitor?
java
junit
thread-safety
Kylar
quelle
quelle
Thread.sleep
dass die Verwendung von Thread.sleep in einem Test im Allgemeinen nur eine schlechte Idee ist. Es entstehen spröde Tests, die je nach Umgebung ("Passes on my machine!") Oder Belastung unvorhersehbar fehlschlagen können. Verlassen Sie sich nicht auf das Timing (verwenden Sie Mocks) oder verwenden Sie Bibliotheken wie Awaitility für asynchrone Tests.Thread.sleep () könnte in den meisten Fällen funktionieren, aber normalerweise warten Sie, wenn Sie warten, tatsächlich auf das Auftreten einer bestimmten Bedingung oder eines bestimmten Zustands. Thread.sleep () garantiert nicht, dass das, worauf Sie warten, tatsächlich passiert ist.
Wenn Sie beispielsweise auf eine Ruhe-Anfrage warten, kehrt diese normalerweise in 5 Sekunden zurück. Wenn Sie jedoch den Ruhezustand für 5 Sekunden an dem Tag einstellen, an dem Ihre Anfrage in 10 Sekunden zurückkommt, schlägt Ihr Test fehl.
Um dies zu beheben, verfügt JayWay über ein großartiges Dienstprogramm namens Awatility, mit dem sichergestellt werden kann, dass ein bestimmter Zustand auftritt, bevor Sie fortfahren .
Es hat auch eine schöne fließende API
https://github.com/jayway/awaitility
quelle
Falls sich Ihr statischer Code-Analysator (wie SonarQube) beschwert, Sie sich aber keinen anderen Weg vorstellen können, als zu schlafen, versuchen Sie es mit einem Hack wie:
Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);
Es ist konzeptionell falsch, aber es ist dasselbe wieThread.sleep(1000)
.Der beste Weg ist natürlich, einen Callable mit Ihrer angemessenen Bedingung zu bestehen, anstatt mit der
true
, die ich habe.https://github.com/awaitility/awaitility
quelle
Duration
Klasse früher hatte, aber seit Version 4 wurde sie in umbenanntDurations
.Sie können die Bibliothek java.util.concurrent.TimeUnit verwenden, die intern Thread.sleep verwendet. Die Syntax sollte folgendermaßen aussehen:
Diese Bibliothek bietet eine klarere Interpretation für die Zeiteinheit. Sie können 'STUNDEN' / 'MINUTEN' / 'SEKUNDEN' verwenden.
quelle
sleep()
Auswirkungen auf den Arbeitsthread?Sie können das
CountDownLatch
Objekt auch wie hier beschrieben verwenden .quelle
Es gibt ein allgemeines Problem: Es ist schwer, sich über die Zeit lustig zu machen. Es ist auch sehr schlecht, einen Code mit langer Laufzeit / Wartezeit in einen Komponententest einzufügen.
Um eine Planungs-API testbar zu machen, habe ich eine Schnittstelle mit einer realen und einer Scheinimplementierung wie dieser verwendet:
Damit können Sie die Zeit in Ihrem Test nachahmen:
Ein fortschrittliches Multithreading-Modell für
Clock
ist natürlich viel komplexer, aber Sie können es beispielsweise mitThreadLocal
Referenzen und einer guten Zeitsynchronisationsstrategie erstellen.quelle