StepVerifier를 사용하여 테스트하기

김기현·2025년 8월 6일

Spring WebFlux

목록 보기
25/28

Project Reactor의 StepVerifier는 리액티브 스트림(Mono/Flux)을 동기적으로 테스트할 수 잇도록 도와주는 유틸리티이다.
비동기적으로 발생하는 이벤트(데이터, 에러, 완료)의 순서를 예측하고 검증하는 데 사용된다.


StepVerifier의 핵심 기능

  • 예측 가능성: 스트림에서 어떤 요소가 방출될지, 언제 에러가 발생하거나 완료될지 예측하고 검증한다.
  • 가독성: expectNext(), expectError(), verifyComplete()와 같은 직관적인 메소드 체인트로 테스트코드를 작성할 수 있어 가독성이 높다.
  • 타임아웃 및 가상 시간: 특정 이벤트가 발생하는 데 걸리는 시간을 검증하거나, withVirtualTime을 사용하여 시간을 빠르게 돌려 테스트 시간을 단축할 수 있다.

사용법

1. 의존성 추가

testImplementation 'io.projectreactor:reactor-test'

2. 기본적인 사용법

StepVerifiercreate()메소드로 스트림을 인자로 받아 시작한다.
이후 예상되는 이벤트들을 메소드 체인으로 연결하고 마지막에 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();      // 스트림이 성공적으로 완료되었는지 검증
    }
}

3. 에러 및 완료 검증

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();                                      // 에러가 발생하면 테스트 종료
    }
}

4. 가상 시간 사용

시간에 의존하는 스트림(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()를 사용하여 특정 시간만큼 가상 시간을 진행시키면, 실제로는 시간이 흐르지 않아도 스트림이 다음 이벤트가 발생한 것처럼 테스트할 수 있다.

profile
백엔드 개발자를 목표로 공부하는 대학생

0개의 댓글