一般的な問題があります:時間を模倣するのは難しいです。また、ユニットテストに実行時間の長いコードや待機中のコードを配置することは非常に悪い習慣です。
したがって、スケジューリング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
、たとえば、参照と適切な時間同期戦略を使用して作成できます。
Thread.sleep
ようなもの は一般に悪い考えです。環境(「マシン上のパス!」)または負荷によっては予期せず失敗する可能性がある脆弱なテストを作成します。タイミングに依存しない(モックを使用)か、非同期テストにAwaitilityなどのライブラリを使用しないでください。