Project Reactor의 StepVerifier는 리액티브 스트림(Mono/Flux)을 동기적으로 테스트할 수 잇도록 도와주는 유틸리티이다.
비동기적으로 발생하는 이벤트(데이터, 에러, 완료)의 순서를 예측하고 검증하는 데 사용된다.
withVirtualTime을 사용하여 시간을 빠르게 돌려 테스트 시간을 단축할 수 있다.testImplementation 'io.projectreactor:reactor-test'
StepVerifier는 create()메소드로 스트림을 인자로 받아 시작한다.
이후 예상되는 이벤트들을 메소드 체인으로 연결하고 마지막에 verify()또는 verifyComplete()를 호출하여 테스트를 실행한다.
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
public class StepVerifierExample {
@Test
void testSimpleFlux() {
Flux<String> flux = Flux.just("hello", "world", "reactor");
StepVerifier.create(flux)
.expectNext("hello") // 다음 요소가 "hello"인지 검증
.expectNext("world") // 다음 요소가 "world"인지 검증
.expectNext("reactor") // 다음 요소가 "reactor"인지 검증
.verifyComplete(); // 스트림이 성공적으로 완료되었는지 검증
}
}
StepVerifier는 에러와 완료 이벤트도 검증할 수 있다.
expectError()를 사용하여 특정 에러가 발생하는지 확인하고, verify()를 호출해 테스트를 종료한다.
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
public class StepVerifierErrorExample {
@Test
void testErrorMono() {
Mono<String> monoWithError = Mono.error(new IllegalArgumentException("Invalid argument"));
StepVerifier.create(monoWithError)
.expectError(IllegalArgumentException.class) // 특정 에러 타입 검증
.verify(); // 에러가 발생하면 테스트 종료
}
}
시간에 의존하는 스트림(ex: delayElements, interval)을 테스트할 때는 withVirtualTime을 사용해 가상의 시간을 진행시켜 실제 대기 시간 없이 테스트를 빠르게 완료할 수 있다.
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import java.time.Duration;
public class StepVerifierVirtualTimeExample {
@Test
void testVirtualTime() {
// 100ms마다 요소를 방출하는 스트림
Flux<Long> longFlux = Flux.interval(Duration.ofMillis(100)).take(3);
StepVerifier.withVirtualTime(() -> longFlux)
.expectSubscription() // 구독이 시작되었는지 확인
.thenAwait(Duration.ofMillis(100)) // 100ms 가상 시간 진행
.expectNext(0L) // 첫 번째 요소 검증
.thenAwait(Duration.ofMillis(100)) // 100ms 가상 시간 진행
.expectNext(1L) // 두 번째 요소 검증
.thenAwait(Duration.ofMillis(100)) // 100ms 가상 시간 진행
.expectNext(2L) // 세 번째 요소 검증
.verifyComplete();
}
}
thenAwait()를 사용하여 특정 시간만큼 가상 시간을 진행시키면, 실제로는 시간이 흐르지 않아도 스트림이 다음 이벤트가 발생한 것처럼 테스트할 수 있다.