同期的に一定の時間待機したいJUnitテストがあります。私のJUnitテストは次のようになります。
@Test
public void testExipres(){
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
//WAIT FOR 2 SECONDS
assertNull(sco.getIfNotExipred("foo"));
}
Thread.currentThread()。wait()を試しましたが、IllegalMonitorStateExceptionがスローされます(予想どおり)。それにいくつかのトリックがありますか、または別のモニターが必要ですか?
Thread.sleep(2000);
はどうですか? :)
Thread.sleep()はほとんどの場合に機能しますが、通常、待機している場合、実際には特定の条件または状態が発生するのを待っています。 Thread.sleep()は、あなたが待っていることが実際に起こったことを保証しません。
たとえば、休憩リクエストを待っている場合、通常5秒で戻りますが、10秒でリクエストが戻ってくる日を5秒間スリープに設定すると、テストは失敗します。
この問題を解決するために、JayWayには Awatility と呼ばれる優れたユーティリティがあります。これは、先に進む前に特定の状態を確実に発生させるのに最適です。
素敵な流なapiもあります
await().until(() ->
{
return yourConditionIsMet();
});
また、説明されている here のようなCountDownLatch
オブジェクトを使用することもできます。
内部でThread.sleepを使用するJava.util.concurrent.TimeUnitライブラリを使用できます。構文は次のようになります。
@Test
public void testExipres(){
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
TimeUnit.MINUTES.sleep(2);
assertNull(sco.getIfNotExipred("foo"));
}
このライブラリは、時間単位のより明確な解釈を提供します。 「HOURS」/「MINUTES」/「SECONDS」を使用できます。
一般的な問題があります:時間をモックするのは難しいです。また、単体テストに長時間実行/待機中のコードを配置することは非常に悪い習慣です。
したがって、スケジューリングAPIをテスト可能にするために、次のような実際の実装と模擬実装のインターフェースを使用しました。
public interface Clock {
public long getCurrentMillis();
public void sleep(long millis) throws InterruptedException;
}
public static class SystemClock implements Clock {
@Override
public long getCurrentMillis() {
return System.currentTimeMillis();
}
@Override
public void sleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
}
public static class MockClock implements Clock {
private final AtomicLong currentTime = new AtomicLong(0);
public MockClock() {
this(System.currentTimeMillis());
}
public MockClock(long currentTime) {
this.currentTime.set(currentTime);
}
@Override
public long getCurrentMillis() {
return currentTime.addAndGet(5);
}
@Override
public void sleep(long millis) {
currentTime.addAndGet(millis);
}
}
これにより、テストの時間を模倣できます。
@Test
public void testExipres() {
MockClock clock = new MockClock();
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
clock.sleep(2000) // WAIT FOR 2 SECONDS
assertNull(sco.getIfNotExpired("foo"));
}
Clock
の高度なマルチスレッドモックはもちろんはるかに複雑ですが、たとえばThreadLocal
参照と適切な時間同期戦略を使用して作成できます。