디버깅
디버그 모드
Hooks.onOperatorDebug();
비용이 많이 드는 동작 과정을 거치기 때문에 -> 처음부터 디버그 모드를 활성화하는 것은 권장하지 않음
checkpoint() 사용
Flux
.just(2, 4, 6, 8)
.zipWith(Flux.just(1, 2, 3, 0), (x, y) -> x/y)
.checkpoint("Example12_4.zipWith.checkpoint", true)
.map(num -> num + 2)
.checkpoint("Example12_4.map.checkpoint", true)
.subscribe(
data -> log.info("# onNext: {}", data),
error -> log.error("# onError:", error)
);
실행 결과
Assembly trace from producer [reactor.core.publisher.FluxZip], described as [Example12_4.zipWith.checkpoint] :
reactor.core.publisher.Flux.checkpoint(Flux.java:3519)
org.example.webflux.FluxMain.main(FluxMain.java:16)
Error has been observed at the following site(s):
*__checkpoint(Example12_4.zipWith.checkpoint) ⇢ at org.example.webflux.FluxMain.main(FluxMain.java:16)
|_ checkpoint ⇢ Example12_4.map.checkpoint
테스팅
의존성 추가
testImplementation 'io.projectreactor:reactor-test'
Signal 이벤트 테스트
public class StepVerifierGeneralTest {
@Test
public void sayHelloReactorTest() {
StepVerifier
.create(Mono.just("Hello world"))
.expectNext("Hello world")
.expectComplete()
.verify();
}
}
Flux 또는 Mono 를 Reactor Sequence 로 정의한 후, 구독 시점에 해당 Opeerator 체인이 시나리오대로 동작하는지 테스트
다음에 발생할 Signal 이 무엇인지, 기대하는 데이터들이 emit 되었는지 등
.as
public class GeneralTestExample {
public static Flux<String> sayHello() {
return Flux
.just("Hello", "Reactor");
}
@Test
public void sayHelloTest() {
StepVerifier
.create(GeneralTestExample.sayHello())
.expectSubscription()
.as("# expect subscription")
.expectNext("Hi")
.as("# expect Hi")
.expectNext("Reactor")
.as("# expect Reactor")
.verifyComplete();
}
java.lang.AssertionError: expectation "# expect Hi" failed (expected value: Hi; actual value: Hello)
시간 기반 테스트
@Test
public void getCOVID19CountTest() {
StepVerifier
.create(TimeBasedTestExample.getCOVID19Count(
Flux.interval(Duration.ofSeconds(3)).take(1)
)
)
.expectSubscription()
.expectNextCount(11)
.expectComplete()
.verify(Duration.ofSeconds(5));
}
지정한 시간 내에 테스트 대상 메서드의 작업이 종료되는지를 확인
.withVirtualTime
@Test
public void getVoteCountTest() {
StepVerifier
.withVirtualTime(() -> TimeBasedTestExample.getVoteCount(
Flux.interval(Duration.ofMinutes(1))
)
)
.expectSubscription()
.expectNoEvent(Duration.ofMinutes(1))
.expectNoEvent(Duration.ofMinutes(1))
.expectNoEvent(Duration.ofMinutes(1))
.expectNoEvent(Duration.ofMinutes(1))
.expectNoEvent(Duration.ofMinutes(1))
.expectNextCount(5)
.expectComplete()
.verify();
}
.withVirtualTime() : StepVerifier 메서드 체인들이 VirtualTimeScheduler 의 제어를 받오록 함
.expectNoEvent(n) 지정된 시간 동안 어떤 이벤트도 발생하지 않을 것이라고 기대하는 동시에
지정한 시간만큼 시간을 앞당긴다는 것
StepVerifier
- Reactor Sequence 에서 발생하는 Signal 이벤트를 테스트
- .withVirtualTime() 과 VirtualTimeScheduler() 등을 이용해서 시간 기반 테스트 진행
- .thenConsumeWhile() 을 이용해서 Backpressure 테스트 진행
- .expectAccessibleContext()를 이용해서 Sequence에 전파되는 Context를 테스트 가능
- .recordWith(), consumeRecordedWith(), expectRecordedMatches() 등을 이용해서 Record 기반 테스트 진행
그외
TestPublisher
개발자가 직접 Signal 을 발생시키면서 원하는 상황을 미세하게 재연하며 테스트 진행
PublisherProbe
조건에 따라 Sequence가 분기되는 경우, Sequence 의 실행 경로를 추적해서 정상적으로 실행되었는지 테스트
- PublisherProbe의 assertWasSubscribed(), assertWasRequested(), assertWasNotCancelled() 등을 통해 Sequence의 기대하는 실행 경로를 Assertion 할 수 있음
'Back-end > 벡엔드' 카테고리의 다른 글
리액티브 프로그래밍 Spring WebFlux를 이용한 Non Blocking 애플리케이션 구현 (0) | 2024.08.03 |
---|---|
도메인 주도 개발 - 도메인서비스 (0) | 2024.05.15 |
도메인 주도 개발 - 이벤트 (0) | 2024.05.15 |
내부망 프로젝트 - SAP HANA DB & Spring Boot (2) | 2024.01.10 |
내부망 프로젝트 - Offline 에서 Spring Boot 개발 Maven 레포지토리 (0) | 2023.10.15 |
댓글