일반적인 문제가 있습니다. 시간을 조롱하기가 어렵습니다. 또한 단위 테스트에 장기 실행 / 대기 코드를 배치하는 것은 정말 나쁜 습관입니다.
그래서 스케줄링 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)
assertNull(sco.getIfNotExpired("foo"));
}
에 대한 고급 멀티 스레딩 모의 Clock
는 물론 훨씬 더 복잡하지만 ThreadLocal
, 예를 들어 참조 및 좋은 시간 동기화 전략을 사용하여 만들 수 있습니다 .
Thread.sleep
이라고 불평 할 것 입니다. 환경 ( "내 머신에 합격!") 또는 부하에 따라 예상치 않게 실패 할 수있는 취성 테스트를 생성합니다. 비동기 테스트를 위해 타이밍에 의존하거나 (모의 사용) Awaitility와 같은 라이브러리를 사용하지 마십시오.