Programing

JUnit 테스트를 기다리려면 어떻게해야합니까?

lottogame 2020. 10. 21. 07:35
반응형

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();
});  

https://github.com/jayway/awaitility


정적 코드 분석기 (예 : SonarQube)가 불만을 제기하지만 잠자기보다는 다른 방법을 생각할 수없는 경우 다음과 같은 해킹을 시도 할 수 있습니다. Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);개념적으로 잘못되었지만 Thread.sleep(1000).

물론 가장 좋은 방법은 true내가 가지고있는 대신 적절한 조건으로 Callable을 전달하는 것입니다.

https://github.com/awaitility/awaitility


여기에CountDownLatch 설명 된 것과 같은 객체를 사용할 수도 있습니다 .


내부적으로 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'를 사용할 수 있습니다.


일반적인 문제가 있습니다. 시간을 조롱하기가 어렵습니다. 또한 단위 테스트에 장기 실행 / 대기 코드를 배치하는 것은 정말 나쁜 습관입니다.

그래서 스케줄링 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예를 들어 참조 및 좋은 시간 동기화 전략을 사용하여 만들 수 있습니다 .

참고 URL : https://stackoverflow.com/questions/15938538/how-can-i-make-a-junit-test-wait

반응형