Ada masalah umum: sulit untuk mengejek waktu. Selain itu, praktik yang sangat buruk untuk menempatkan kode yang berjalan / menunggu dalam waktu lama dalam pengujian unit.
Jadi, untuk membuat API penjadwalan dapat diuji, saya menggunakan antarmuka dengan implementasi nyata dan tiruan seperti ini:
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);
}
}
Dengan ini, Anda bisa meniru waktu dalam ujian Anda:
@Test
public void testExipres() {
MockClock clock = new MockClock();
SomeCacheObject sco = new SomeCacheObject();
sco.putWithExipration("foo", 1000);
clock.sleep(2000)
assertNull(sco.getIfNotExpired("foo"));
}
Sebuah tiruan multi-threading tingkat lanjut untuk Clock
jauh lebih kompleks, tentu saja, tetapi Anda dapat membuatnya dengan ThreadLocal
referensi dan strategi sinkronisasi waktu yang baik, misalnya.
Thread.sleep
mengatakan sesuatu seperti Menggunakan