有一个普遍的问题:很难模拟时间。另外,在单元测试中放置长时间运行/等待的代码确实是一种不好的做法。
因此,为了使Schedule 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
说在测试中使用