@Test(timeout = 1000L) public void lowRequestCheckCanBeDisabled() { StepVerifier.create(Flux.just(1, 2), StepVerifierOptions.create().initialRequest(1).checkUnderRequesting(false)) .expectNext(1) .thenConsumeWhile(s -> s == 1); //don't verify, this alone would throw an exception if check activated }
public void plugHooks(StepVerifierOptions verifierOptions) { plugHooks(); Context userContext = verifierOptions.getInitialContext(); verifierOptions.withInitialContext(Operators.enableOnDiscard(userContext, discardedElements::offer)); }
Supplier<? extends VirtualTimeScheduler> vtsLookup, long n) { return withVirtualTime(scenarioSupplier, StepVerifierOptions.create() .initialRequest(n) .virtualTimeSchedulerSupplier(vtsLookup));
/** * Prepare a new {@code StepVerifier} in an uncontrolled environment: * {@link Step#thenAwait} will block in real time. * Each {@link #verify()} will fully (re)play the scenario. * The verification will request a specified amount of values. * * @param publisher the publisher to subscribe to and verify * @param n the amount of items to request * * @return a builder for expectation declaration and ultimately verification. */ static <T> FirstStep<T> create(Publisher<? extends T> publisher, long n) { return create(publisher, StepVerifierOptions.create().initialRequest(n)); }
DefaultStepVerifierBuilder(StepVerifierOptions options, @Nullable Supplier<? extends Publisher<? extends T>> sourceSupplier) { this.initialRequest = options.getInitialRequest(); this.options = options; this.errorFormatter = options.getScenarioName() == null ? NO_NAME_ERROR_FORMATTER : new ErrorFormatter(options.getScenarioName()); this.vtsLookup = options.getVirtualTimeSchedulerSupplier(); this.sourceSupplier = sourceSupplier; this.script = new ArrayList<>(); this.defaultFirstStep = newOnSubscribeStep(errorFormatter, "defaultOnSubscribe"); this.script.add(defaultFirstStep); this.hangCheckRequested = initialRequest; }
@Test public void withInitialContextButNoPropagation() { StepVerifier.create(Mono.just(1), //just(1) uses a ScalarSubscription which can't be resolved to a chain of parents StepVerifierOptions.create().withInitialContext(Context.of("foo", "bar"))) .expectNoAccessibleContext() .expectNext(1) .verifyComplete(); }
@Test public void testWithDescriptionAndScenarioName() { StepVerifierOptions options = StepVerifierOptions.create() .initialRequest(3) .scenarioName("some scenario name"); StepVerifier stepVerifier = StepVerifier .create(Flux.just("foo", "bar", "baz"), options) .expectNext("foo") .as("first") .expectNext("bar") .as("second") .expectNext("bar") .as("third") .as("this is ignored") .expectComplete() .log(); assertThatExceptionOfType(AssertionError.class) .isThrownBy(stepVerifier::verify) .withMessage("[some scenario name] expectation \"third\" failed (expected value: bar; actual value: baz)"); }
@Test public void testDurationFailureWithScenarioName() { StepVerifierOptions options = StepVerifierOptions.create() .scenarioName("some scenario name"); StepVerifier stepVerifier = StepVerifier .create(Mono.delay(Duration.ofMillis(100)), options) .expectNextCount(1) .expectComplete(); assertThatExceptionOfType(AssertionError.class) .isThrownBy(() -> stepVerifier.verify(Duration.ofMillis(10))) .withMessageStartingWith("[some scenario name] VerifySubscriber timed out on reactor.core.publisher.MonoDelay$MonoDelayRunnable@"); }
Supplier<? extends Publisher<? extends T>> scenarioSupplier, StepVerifierOptions options) { DefaultStepVerifierBuilder.checkPositive(options.getInitialRequest()); Objects.requireNonNull(options.getVirtualTimeSchedulerSupplier(), "vtsLookup"); Objects.requireNonNull(scenarioSupplier, "scenarioSupplier");
/** * Converts the {@link StepVerifier} to a {@link Subscriber}, leaving all the * lifecycle management to the user. Most notably: * <ul> * <li>no subscription is performed * <li>no {@link VirtualTimeScheduler} is registered in the Schedulers factories * </ul> * <p> * However if a {@link VirtualTimeScheduler} supplier was passed in originally * it will be invoked and the resulting scheduler will be affected by time * manipulation methods. That scheduler can be retrieved from the subscriber's * {@link DefaultVerifySubscriber#virtualTimeScheduler() virtualTimeScheduler()} * method. */ DefaultVerifySubscriber<T> toSubscriber() { VirtualTimeScheduler vts = null; if (parent.vtsLookup != null) { vts = parent.vtsLookup.get(); } return new DefaultVerifySubscriber<>( this.parent.script, this.parent.errorFormatter, this.parent.initialRequest, this.requestedFusionMode, this.expectedFusionMode, this.debugEnabled, this.parent.options.getInitialContext(), vts); }
/** * Create a new default set of options for a {@link StepVerifier} that can be tuned * using the various available non-getter methods (which can be chained). */ public static StepVerifierOptions create() { return new StepVerifierOptions(); }
static <T> StepVerifier.FirstStep<T> newVerifier(StepVerifierOptions options, Supplier<? extends Publisher<? extends T>> scenarioSupplier) { DefaultStepVerifierBuilder.checkPositive(options.getInitialRequest()); Objects.requireNonNull(scenarioSupplier, "scenarioSupplier"); return new DefaultStepVerifierBuilder<>(options, scenarioSupplier); }
@Test public void withInitialContext() { StepVerifier.create(Mono.subscriberContext(), StepVerifierOptions.create().withInitialContext(Context.of("foo", "bar"))) .assertNext(c -> Assertions.assertThat(c.getOrDefault("foo", "baz")) .isEqualTo("bar")) .verifyComplete(); }
@Test public void discardOnFlushWithoutRequest() { TestPublisher<Integer> testPublisher = TestPublisher.createNoncompliant(TestPublisher.Violation.REQUEST_OVERFLOW); StepVerifier.create(testPublisher .flux() .bufferTimeout(10, Duration.ofMillis(200)), StepVerifierOptions.create().initialRequest(0)) .then(() -> testPublisher.emit(1, 2, 3)) .thenAwait(Duration.ofMillis(250)) .expectErrorMatches(Exceptions::isOverflow) .verifyThenAssertThat() .hasDiscardedExactly(1, 2, 3); }
DefaultStepVerifierBuilder(StepVerifierOptions options, @Nullable Supplier<? extends Publisher<? extends T>> sourceSupplier) { this.initialRequest = options.getInitialRequest(); this.options = options; this.errorFormatter = options.getScenarioName() == null ? NO_NAME_ERROR_FORMATTER : new ErrorFormatter(options.getScenarioName()); this.vtsLookup = options.getVirtualTimeSchedulerSupplier(); this.sourceSupplier = sourceSupplier; this.script = new ArrayList<>(); this.defaultFirstStep = newOnSubscribeStep(errorFormatter, "defaultOnSubscribe"); this.script.add(defaultFirstStep); this.hangCheckRequested = initialRequest; }
Supplier<? extends Publisher<? extends T>> scenarioSupplier, StepVerifierOptions options) { DefaultStepVerifierBuilder.checkPositive(options.getInitialRequest()); Objects.requireNonNull(options.getVirtualTimeSchedulerSupplier(), "vtsLookup"); Objects.requireNonNull(scenarioSupplier, "scenarioSupplier");
this.expectedFusionMode, this.debugEnabled, this.parent.options.getInitialContext(), vts);
/** * Create a new default set of options for a {@link StepVerifier} that can be tuned * using the various available non-getter methods (which can be chained). */ public static StepVerifierOptions create() { return new StepVerifierOptions(); }
static <T> StepVerifier.FirstStep<T> newVerifier(StepVerifierOptions options, Supplier<? extends Publisher<? extends T>> scenarioSupplier) { DefaultStepVerifierBuilder.checkPositive(options.getInitialRequest()); Objects.requireNonNull(scenarioSupplier, "scenarioSupplier"); return new DefaultStepVerifierBuilder<>(options, scenarioSupplier); }
@Test public void recursiveCountdownBackpressure() { StepVerifier.create(Mono.just(10) .expand(countDown), StepVerifierOptions.create() .initialRequest(0) .checkUnderRequesting(false)) .thenRequest(1) .expectNext(10) .thenRequest(3) .expectNext(9, 8, 7) .thenRequest(4) .expectNext(6, 5, 4, 3) .thenRequest(3) .expectNext(2, 1, 0) .verifyComplete(); }