@Test public void whenMonoError() { MonoProcessor<Tuple2<Integer, Integer>> mp = MonoProcessor.create(); StepVerifier.create(Mono.zip(Mono.<Integer>error(new Exception("test1")), Mono.<Integer>error(new Exception("test2"))) .subscribeWith(mp)) .then(() -> assertThat(mp.isError()).isTrue()) .then(() -> assertThat(mp.isSuccess()).isFalse()) .then(() -> assertThat(mp.isTerminated()).isTrue()) .verifyErrorSatisfies(e -> assertThat(e).hasMessage("test1")); }
@Test public void filterMonoNot() { MonoProcessor<Integer> mp = MonoProcessor.create(); StepVerifier.create(Mono.just(1).filter(s -> s % 2 == 0).subscribeWith(mp)) .then(() -> assertThat(mp.isError()).isFalse()) .then(() -> assertThat(mp.isSuccess()).isTrue()) .then(() -> assertThat(mp.peek()).isNull()) .then(() -> assertThat(mp.isTerminated()).isTrue()) .verifyComplete(); } }
@Test public void otherwiseReturnErrorUnfilter2() { MonoProcessor<Integer> mp = MonoProcessor.create(); StepVerifier.create(Mono.<Integer>error(new TestException()) .onErrorReturn(RuntimeException.class::isInstance, 1) .subscribeWith(mp)) .then(() -> assertThat(mp.isError()).isTrue()) .then(() -> assertThat(mp.isSuccess()).isFalse()) .then(() -> assertThat(mp.isTerminated()).isTrue()) .verifyError(TestException.class); } }
@Test public void failAsyncInnerFusion() { UnicastProcessor<Integer> up = UnicastProcessor.create(); StepVerifier.create(Flux.just(1) .hide() .flatMap(f -> up, 1)) .then(() -> up.onNext(1)) .then(() -> up.onNext(2)) .then(() -> up.onError(new Exception("test"))) .expectNext(1, 2) .verifyErrorMessage("test"); }
@Test public void failOverflowScalar() { TestPublisher<Integer> ts = TestPublisher.createNoncompliant(TestPublisher.Violation.REQUEST_OVERFLOW); StepVerifier.create(ts.flux() .flatMap(Flux::just, 1), 0) .then(() -> ts.emit(1, 2)) .verifyErrorMatches(Exceptions::isOverflow); }
@Test public void subscribeWithAsyncFusion() { Processor<Integer, Integer> processor = EmitterProcessor.create(16); StepVerifier.create(processor) .then(() -> Flux.range(1, 5).publishOn(Schedulers.elastic()).subscribe(processor)) .expectNext(1, 2, 3, 4, 5) .expectComplete() .verify(Duration.ofSeconds(1)); }
@Test public void subscribeWithSyncFusionSingle() { Processor<Integer, Integer> processor = EmitterProcessor.create(16); StepVerifier.create(processor) .then(() -> Flux.just(1).subscribe(processor)) .expectNext(1) .expectComplete() .verify(Duration.ofSeconds(1)); }
@Test public void apiTakeSchedulerShortcircuits() { VirtualTimeScheduler vts = VirtualTimeScheduler.create(); StepVerifier.create( Mono.delay(Duration.ofMillis(200)) .take(Duration.ofSeconds(10), vts) ) .then(() -> vts.advanceTimeBy(Duration.ofSeconds(10))) .verifyComplete(); }
@SuppressWarnings("unchecked") final StepVerifier.Step<O> inputFusedError(OperatorScenario<I, PI, O, PO> scenario) { UnicastProcessor<I> up = UnicastProcessor.create(); return StepVerifier.create(scenario.body() .apply(up.as(f -> withFluxSource(new FluxFuseableExceptionOnPoll<>( f, exception()))))) .then(testUnicastDropPath(scenario, up)); }
final StepVerifier.Step<O> inputConditionalOutputConditional(OperatorScenario<I, PI, O, PO> scenario) { TestPublisher<I> ts = TestPublisher.create(); return StepVerifier.create(scenario.body() .andThen(this::conditional) .apply(withFluxSource(ts.flux()))) .then(() -> testPublisherSource(scenario, ts)); }
@Test public void failNextIfTerminatedTakeFused() { UnicastProcessor<Integer> up = UnicastProcessor.create(); Hooks.onNextDropped(t -> assertThat(t).isEqualTo(1)); StepVerifier.create(up.take(2)) .then(() -> up.actual.onComplete()) .then(() -> up.actual.onNext(1)) .verifyComplete(); Hooks.resetOnNextDropped(); }
@Test public void symmetricBlackboxProcessor(){ UnicastProcessor<Integer> upstream = UnicastProcessor.create(); FluxProcessor<Integer, Integer> processor = FluxProcessor.wrap(upstream, upstream); StepVerifier.create(processor) .then(() -> Flux.just(1).subscribe(processor)) .expectNext(1) .verifyComplete(); }
@Test public void coldDisallowsOverflow() { TestPublisher<String> publisher = TestPublisher.createCold(); StepVerifier.create(publisher, 1) .then(() -> publisher.next("foo")).as("should pass") .then(() -> publisher.emit("bar")).as("should fail") .expectNext("foo") .expectErrorMatches(e -> e instanceof IllegalStateException && "Can't deliver value due to lack of requests".equals(e.getMessage())) .verify(); publisher.assertNoRequestOverflow(); }
@Test public void emitCompletes() { TestPublisher<String> publisher = TestPublisher.create(); StepVerifier.create(publisher) .then(() -> publisher.emit("foo", "bar")) .expectNextCount(2) .expectComplete() .verify(); }
@Test public void expectSubscribers() { TestPublisher<String> publisher = TestPublisher.create(); assertThatExceptionOfType(AssertionError.class) .isThrownBy(publisher::assertSubscribers) .withMessage("Expected subscribers"); StepVerifier.create(publisher) .then(() -> publisher.assertSubscribers() .complete()) .expectComplete() .verify(); }
@Test public void discardOnEmitOverflow() { final TestPublisher<Integer> publisher = TestPublisher.createNoncompliant(TestPublisher.Violation.REQUEST_OVERFLOW); StepVerifier.create(publisher.flux() .buffer(Mono.never()), StepVerifierOptions.create().initialRequest(0)) .then(() -> publisher.emit(1, 2, 3)) .expectErrorMatches(Exceptions::isOverflow) .verifyThenAssertThat() .hasDiscardedExactly(1, 2, 3); } }
@Test public void assertNextWithSubscribeOnJust() { assertThatExceptionOfType(AssertionError.class) .isThrownBy( StepVerifier.create(Flux.just(1) .subscribeOn(Schedulers.newSingle("test"))) .then(() -> System.out.println("foo")) .assertNext(v -> assertThat(v).isNull()) .thenCancel() ::verify); }
@Test // SPR-17054 public void unsupportedMediaTypeShouldConsumeAndCancel() { NettyDataBufferFactory factory = new NettyDataBufferFactory(new PooledByteBufAllocator(true)); NettyDataBuffer buffer = factory.wrap(ByteBuffer.wrap("spring".getBytes(StandardCharsets.UTF_8))); TestPublisher<DataBuffer> body = TestPublisher.create(); MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); response.getHeaders().setContentType(MediaType.APPLICATION_PDF); response.setBody(body.flux()); BodyExtractor<Mono<User>, ReactiveHttpInputMessage> extractor = BodyExtractors.toMono(User.class); StepVerifier.create(extractor.extract(response, this.context)) .then(() -> { body.assertWasSubscribed(); body.emit(buffer); }) .expectErrorSatisfies(throwable -> { assertTrue(throwable instanceof UnsupportedMediaTypeException); try { buffer.release(); Assert.fail("releasing the buffer should have failed"); } catch (IllegalReferenceCountException exc) { } body.assertCancelled(); }).verify(); }
@Test public void toMonoVoidAsClientShouldConsumeAndCancel() { DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); DefaultDataBuffer dataBuffer = factory.wrap(ByteBuffer.wrap("foo".getBytes(StandardCharsets.UTF_8))); TestPublisher<DataBuffer> body = TestPublisher.create(); BodyExtractor<Mono<Void>, ReactiveHttpInputMessage> extractor = BodyExtractors.toMono(Void.class); MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); response.setBody(body.flux()); StepVerifier.create(extractor.extract(response, this.context)) .then(() -> { body.assertWasSubscribed(); body.emit(dataBuffer); }) .verifyComplete(); body.assertCancelled(); }
@Test public void toMonoVoidAsClientWithEmptyBody() { TestPublisher<DataBuffer> body = TestPublisher.create(); BodyExtractor<Mono<Void>, ReactiveHttpInputMessage> extractor = BodyExtractors.toMono(Void.class); MockClientHttpResponse response = new MockClientHttpResponse(HttpStatus.OK); response.setBody(body.flux()); StepVerifier.create(extractor.extract(response, this.context)) .then(() -> { body.assertWasSubscribed(); body.complete(); }) .verifyComplete(); }