source

JUnit 테스트는 어떻게 하면 대기시킬 수 있나요?

bestscript 2023. 1. 26. 09:14

JUnit 테스트는 어떻게 하면 대기시킬 수 있나요?

동기적으로 기다리고 싶은 JUnit 시험이 있어요.JUnit 테스트는 다음과 같습니다.

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);
    // WAIT FOR 2 SECONDS
    assertNull(sco.getIfNotExipred("foo"));
}

는 는 i i는노노 i i i i i.Thread.currentThread().wait()단, Ilgal Monitor State Exception(예상대로)을 슬로우합니다.

뭔가 요령이 있는 건가요, 아니면 다른 모니터가 필요한 건가요?

는 요?Thread.sleep(2000);? :)

Thread.sleep()은 대부분의 경우 동작할 수 있지만 일반적으로 대기하고 있는 경우에는 실제로 특정 조건 또는 상태가 발생할 때까지 대기하고 있습니다.실.sleep()은 기다리는 것이 실제로 발생했음을 보증하지 않습니다.

예를 들어 rest 요청을 기다리는 경우 보통 5초 후에 반환되지만 요청이 돌아오는 날 sleep을 5초로 설정하면 테스트는 실패합니다.

이 문제를 해결하기 위해 JayWay에는 Awability라는 뛰어난 유틸리티가 있습니다.이 유틸리티는 특정 조건이 발생하기 전에 확실하게 하기 위한 것입니다.

유창한 api도 멋집니다.

await().until(() -> 
{
    return yourConditionIsMet();
});  

https://github.com/jayway/awaitility

sleep이 할 수 과 같이 해킹을 .Awaitility.await().pollDelay(Durations.ONE_SECOND).until(() -> true);이은 '', '아니다', '아니다'와 .Thread.sleep(1000).

방법은이지 콜러블을 패스하는 것은 아닙니다.true내가 가지고 있지.

https://github.com/awaitility/awaitility

java.util.concurrent를 사용할 수 있습니다.스레드를 내부적으로 사용하는 TimeUnit 라이브러리.sleep. 구문은 다음과 같습니다.

@Test
public void testExipres(){
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExipration("foo", 1000);

    TimeUnit.MINUTES.sleep(2);

    assertNull(sco.getIfNotExipred("foo"));
}

이 라이브러리는 시간 단위를 보다 명확하게 해석할 수 있습니다.'HOURS'/'MINUTS'/'SEConds'를 사용할 수 있습니다.

에서 CountDownLatch간단한 해결책입니다.「 」의 「 」의 「 」

private final CountDownLatch waiter = new CountDownLatch(1);

필요한 경우 테스트에서 다음을 수행합니다.

waiter.await(1000 * 1000, TimeUnit.NANOSECONDS); // 1ms

굳이 말할 필요는 없겠지만, 대기 시간은 짧게 하고, 너무 많은 장소에서 대기하지 않도록 주의해 주세요.

,도할 수 .CountDownLatch여기서 설명하는 것과 같은 오브젝트.

Mockito(Spring Boot 프로젝트에 대한 전이 종속성을 통해 이미 제공됨)에는 각각 비동기 이벤트가 발생할 때까지 대기하는 몇 가지 방법이 있습니다.

현재 우리에게 매우 적합한 간단한 패턴은 다음과 같습니다.

// ARRANGE – instantiate Mocks, setup test conditions

// ACT – the action to test, followed by:
Mockito.verify(myMockOrSpy, timeout(5000).atLeastOnce()).delayedStuff();
// further execution paused until `delayedStuff()` is called – or fails after timeout

// ASSERT – assertThat(...)

@fernando-cejas이 글에서 조금 더 복잡하고 정교한 두 가지를 설명합니다.


여기에 제시된 상위 답변에 대한 긴급한 조언은 다음과 같습니다. 테스트를 통해

  1. 가능한 한 빨리 끝내다
  2. 테스트 환경에 관계없이 일관된 결과를 얻을 수 있습니다('불편').

...그래서 그냥 바보 같은 짓은 하지 마세요.Thread.sleep()테스트 코드에 입력해 주세요.

대신 생산 코드에 의존성 주입(또는 "더러움"으로 인해 일부 모킹 가능/스파이 가능한 메서드가 노출됨)을 사용하도록 한 다음 Mockito, Awaitly, Concurrent Unit 등을 사용하여 어설션이 발생하기 전에 비동기 전제 조건이 충족되는지 확인하십시오.

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

그래서 스케줄링 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 testExpiration() {
    MockClock clock = new MockClock();
    SomeCacheObject sco = new SomeCacheObject();
    sco.putWithExpiration("foo", 1000);
    clock.sleep(2000) // wait for 2 seconds
    assertNull(sco.getIfNotExpired("foo"));
}

고급 멀티스레딩 모크:Clock물론 훨씬 더 복잡하지만, 당신은 그것을 만들 수 있습니다.ThreadLocal예를 들어 참조 및 양호한 시간 동기화 전략입니다.

스레드 사용.시험에서 자는 것은 좋은 연습이 아니다.이로 인해 환경("Pass on my machine!" 또는 부하에 따라 예측 불가능한 테스트가 발생할 수 있습니다.타이밍에 의존하거나(모크 사용), 비동기 테스트를 위해 대기 등의 라이브러리를 사용하지 마십시오.

Dependency : testImplementation 'org.awaitility:awaitility:3.0.0'

await().pollInterval(Duration.FIVE_SECONDS).atLeast(Duration.FIVE_SECONDS).atMost(Duration.FIVE_SECONDS).untilAsserted(() -> {
      // your assertion
    });

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