[java] JUnit 테스트를 기다리려면 어떻게해야합니까?
동 기적으로 일정 시간 동안 기다리려는 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 초 후에 반환되지만 수면을 5 초로 설정하면 요청이 10 초 후에 다시 돌아 오는 날 테스트가 실패합니다.
이 문제를 해결하기 위해 JayWay에는 진행 하기 전에 특정 상태가 발생하도록 보장하는 Awatility 라는 훌륭한 유틸리티 가 있습니다.
유창한 API도 있습니다.
await().until(() ->
{
return yourConditionIsMet();
});
답변
정적 코드 분석기 (예 : SonarQube)가 불만을 제기하지만 잠자기보다는 다른 방법을 생각할 수없는 경우 다음과 같은 해킹을 시도 할 수 있습니다.
Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);
개념적으로 잘못되었지만 Thread.sleep(1000)
.
물론 가장 좋은 방법은 true
내가 가지고있는 대신 적절한 조건으로 Callable을 전달하는 것입니다.
답변
내부적으로 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’를 사용할 수 있습니다.
답변
여기에CountDownLatch
설명 된 것과 같은 객체를 사용할 수도 있습니다 .
답변
일반적인 문제가 있습니다. 시간을 조롱하기가 어렵습니다. 또한 단위 테스트에 장기 실행 / 대기 코드를 배치하는 것은 정말 나쁜 습관입니다.
그래서 스케줄링 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
, 예를 들어 참조 및 좋은 시간 동기화 전략을 사용하여 만들 수 있습니다 .
답변
테스트에서 지연을 생성하는 것이 절대적으로 필요하다면 CountDownLatch
간단한 해결책입니다. 테스트 클래스에서 다음을 선언하십시오.
private final CountDownLatch waiter = new CountDownLatch(1);
필요한 경우 테스트에서 :
waiter.await(1000 * 1000, TimeUnit.NANOSECONDS); // 1ms
말할 필요도 없을 수도 있지만 대기 시간을 작게 유지하고 너무 많은 장소에 대기를 누적하지 않아야한다는 점을 명심하십시오.