reactor.test.StepVerifier Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2016 Pivotal Software Inc, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package reactor.test;
import java.time.Duration;
import java.util.Collection;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.Fuseable;
import reactor.core.publisher.Hooks;
import reactor.test.scheduler.VirtualTimeScheduler;
import reactor.util.function.Tuple2;
/**
* A {@link StepVerifier} is a verifiable, blocking script usually produced by
* terminal expectations of the said script.
* - Create a {@code
* StepVerifier} builder using {@link #create} or {@link #withVirtualTime}
* - Set individual up value expectations using
* {@link Step#expectNext}, {@link Step#expectNextMatches(Predicate)},
* {@link Step#expectNextCount(long)} or
* {@link Step#expectNextSequence(Iterable)}
* .
- Set up
* subscription actions using either
* {@link Step#thenRequest(long) thenRequest(long)} or {@link
* Step#thenCancel() thenCancel()}.
- Build the {@code
* StepVerifier} using {@link LastStep#expectComplete},
* {@link LastStep#expectError}, {@link
* LastStep#expectError(Class) expectError(Class)}, {@link
* LastStep#expectErrorMatches(Predicate) expectErrorMatches(Predicate)}, or {@link
* LastStep#thenCancel}.
- Subscribe the built {@code
* StepVerifier} to a {@code Publisher}.
- Verify the expectations using
* either {@link #verify()} or {@link #verify(Duration)}.
- If any expectations
* failed, an {@code AssertionError} will be thrown indicating the failures.
*
* For example:
*
* StepVerifier.create(Flux.just("foo", "bar"))
* .expectNext("foo")
* .expectNext("bar")
* .expectComplete()
* .verify();
*
*
* @author Arjen Poutsma
* @author Stephane Maldini
*/
public interface StepVerifier {
/**
* Prepare a new {@code StepVerifier} in an uncontrolled environment: Expect non-virtual
* blocking
* wait via
* {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario.
*
* @param publisher the publisher to subscribe to
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures
*/
static FirstStep create(Publisher extends T> publisher) {
return create(publisher, Long.MAX_VALUE);
}
/**
* Prepare a new {@code StepVerifier} in an uncontrolled environment: Expect non-virtual
* blocking
* wait via
* {@link Step#thenAwait}. 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
* @param n the amount of items to request
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures, or when the verification
* times out
*/
static FirstStep create(Publisher extends T> publisher,
long n) {
return create(publisher, StepVerifierOptions.create().initialRequest(n));
}
/**
* Prepare a new {@code StepVerifier} in an uncontrolled environment: Expect non-virtual
* blocking wait via {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario. The verification will request a specified amount of values according to
* the {@link StepVerifierOptions options} passed.
*
* @param publisher the publisher to subscribe to
* @param options the options for the verification
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures, or when the verification
* times out
*/
static FirstStep create(Publisher extends T> publisher, StepVerifierOptions options) {
return DefaultStepVerifierBuilder.newVerifier(options, () -> publisher);
}
/**
* Prepare a new {@code StepVerifier} in a controlled environment using
* {@link VirtualTimeScheduler} to schedule and expect virtual wait via
* {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario. The verification will request an unbounded amount of values.
*
* @param scenarioSupplier a mandatory supplier of the {@link Publisher} to test
* @param the type of the subscriber
*
* @return a builder for setting up value expectations
*/
static FirstStep withVirtualTime(Supplier extends Publisher extends T>> scenarioSupplier) {
return withVirtualTime(scenarioSupplier, Long.MAX_VALUE);
}
/**
* @deprecated to be removed in 3.1.0 for parameter ordering harmonization. Please
* use {@link #withVirtualTime(Supplier, long)} instead.
*/
@Deprecated
static FirstStep withVirtualTime(long n,
Supplier extends Publisher extends T>> scenarioSupplier) {
return withVirtualTime(scenarioSupplier, () -> VirtualTimeScheduler.getOrSet(), n);
}
/**
* Prepare a new {@code StepVerifier} in a controlled environment using
* {@link VirtualTimeScheduler} to schedule and expect virtual wait via
* {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario. The verification will request a specified amount of values.
*
* @param scenarioSupplier a mandatory supplier of the {@link Publisher} to test
* @param n the amount of items to request (must be >= 0)
* @param the type of the subscriber
*
* @return a builder for setting up value expectations
*/
static FirstStep withVirtualTime(Supplier extends Publisher extends T>> scenarioSupplier,
long n) {
return withVirtualTime(scenarioSupplier, () -> VirtualTimeScheduler.getOrSet(), n);
}
/**
* @deprecated to be removed in 3.1.0 for parameter ordering harmonization. Please
* use {@link #withVirtualTime(Supplier, Supplier, long)} instead.
*/
@Deprecated
static FirstStep withVirtualTime(long n,
Supplier extends Publisher extends T>> scenarioSupplier,
Supplier extends VirtualTimeScheduler> vtsLookup) {
DefaultStepVerifierBuilder.checkPositive(n);
Objects.requireNonNull(scenarioSupplier, "scenarioSupplier");
Objects.requireNonNull(vtsLookup, "vtsLookup");
StepVerifierOptions options = StepVerifierOptions.create()
.initialRequest(n)
.virtualTimeSchedulerSupplier(vtsLookup);
return DefaultStepVerifierBuilder.newVerifier(options,
scenarioSupplier);
}
/**
* Create a new {@code StepVerifier} in a parameterized environment using
* passed
* {@link VirtualTimeScheduler} to schedule and expect virtual wait via
* {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario. The verification will request a specified amount of values.
*
* @param scenarioSupplier a mandatory supplier of the {@link Publisher} to test
* @param vtsLookup a mandatory {@link VirtualTimeScheduler} lookup to use in {@code
* thenAwait}
* @param n the amount of items to request (must be >= 0)
* @param the type of the subscriber
*
* @return a builder for setting up value expectations
*/
static FirstStep withVirtualTime(
Supplier extends Publisher extends T>> scenarioSupplier,
Supplier extends VirtualTimeScheduler> vtsLookup,
long n) {
return withVirtualTime(scenarioSupplier, StepVerifierOptions.create()
.initialRequest(n)
.virtualTimeSchedulerSupplier(vtsLookup));
}
/**
* Create a new {@code StepVerifier} in a parameterized environment using
* passed {@link VirtualTimeScheduler} to schedule and expect virtual wait via
* {@link Step#thenAwait}. Each {@link #verify()} will fully (re)play the
* scenario. The verification will request a specified amount of values according to
* the provided {@link StepVerifierOptions options}.
*
* @param scenarioSupplier a mandatory supplier of the {@link Publisher} to test
* @param options the verification options, including a mandatory
* {@link VirtualTimeScheduler} lookup to use in {@code thenAwait}
* @param the type of the subscriber
*
* @return a builder for setting up value expectations
*/
static FirstStep withVirtualTime(
Supplier extends Publisher extends T>> scenarioSupplier,
StepVerifierOptions options) {
DefaultStepVerifierBuilder.checkPositive(options.getInitialRequest());
Objects.requireNonNull(options.getVirtualTimeSchedulerSupplier(), "vtsLookup");
Objects.requireNonNull(scenarioSupplier, "scenarioSupplier");
return DefaultStepVerifierBuilder.newVerifier(options,
scenarioSupplier);
}
/**
* Activate debug logging of a description of the test scenario, as well as
* some details about certain verification steps.
*
* @return the verifier for final {@link #verify()} call
*/
StepVerifier log();
/**
* Verify the signals received by this subscriber. This method will
* block indefinitely until the stream has been terminated (either
* through {@link Subscriber#onComplete()}, {@link Subscriber#onError(Throwable)} or
* {@link Subscription#cancel()}).
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures
*/
Duration verify() throws AssertionError;
/**
* Verify the signals received by this subscriber. This method will
* block for the given duration or until the stream has been
* terminated (either through {@link Subscriber#onComplete()},
* {@link Subscriber#onError(Throwable)} or
* {@link Subscription#cancel()}).
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures, or when the verification
* times out
*/
Duration verify(Duration duration) throws AssertionError;
/**
* {@link #verify() Verifies} the signals received by this subscriber, then exposes
* various {@link Assertions assertion methods} on the final state.
*
* Note this method will block indefinitely until the stream has
* been terminated (either through {@link Subscriber#onComplete()},
* {@link Subscriber#onError(Throwable)} or {@link Subscription#cancel()}).
*
* @return the {@link Duration} of the verification
*
* @throws AssertionError in case of expectation failures
*/
Assertions verifyThenAssertThat();
/**
* Define a builder for terminal states.
*/
interface LastStep {
/**
* Expect an error and consume with the given consumer. Any {@code
* AssertionError}s thrown by the consumer will be rethrown during {@linkplain
* #verify() verification}.
*
* @param consumer the consumer for the exception
*
* @return the built verification
*/
StepVerifier consumeErrorWith(Consumer consumer);
/**
* Expect an unspecified error.
*
* @return the built verification
*
* @see Subscriber#onError(Throwable)
*/
StepVerifier expectError();
/**
* Expect an error of the specified type.
*
* @param clazz the expected error type
*
* @return the built verification
*
* @see Subscriber#onError(Throwable)
*/
StepVerifier expectError(Class extends Throwable> clazz);
/**
* Expect an error with the specified message.
*
* @param errorMessage the expected error message
*
* @return the built verification
*
* @see Subscriber#onError(Throwable)
*/
StepVerifier expectErrorMessage(String errorMessage);
/**
* Expect an error and evaluate with the given predicate.
*
* @param predicate the predicate to test on the next received error
*
* @return the built verification
*
* @see Subscriber#onError(Throwable)
*/
StepVerifier expectErrorMatches(Predicate predicate);
/**
* Expect the completion signal.
*
* @return the built verification
*
* @see Subscriber#onComplete()
*/
StepVerifier expectComplete();
/**
* Cancel the underlying subscription.
*
* @return the built verification
*
* @see Subscription#cancel()
*/
StepVerifier thenCancel();
/**
* Trigger the {@link #verify() verification}, expecting an unspecified error
* as terminal event.
*
* This is a convenience method that calls {@link #verify()} in addition to the
* expectation. Explicitly use the expect method and verification method
* separately if you need something more specific (like activating logging or
* putting a timeout).
*
* @return the {@link Duration} of the verification
*
* @see #expectError()
* @see #verify()
* @see Subscriber#onError(Throwable)
*/
Duration verifyError();
/**
* Trigger the {@link #verify() verification}, expecting an error of the specified
* type as terminal event.
*
* This is a convenience method that calls {@link #verify()} in addition to the
* expectation. Explicitly use the expect method and verification method
* separately if you need something more specific (like activating logging or
* putting a timeout).
*
* @param clazz the expected error type
* @return the {@link Duration} of the verification
*
* @see #expectError(Class)
* @see #verify()
* @see Subscriber#onError(Throwable)
*/
Duration verifyError(Class extends Throwable> clazz);
/**
* Trigger the {@link #verify() verification}, expecting an error with the
* specified messagee as terminal event.
*
* This is a convenience method that calls {@link #verify()} in addition to the
* expectation. Explicitly use the expect method and verification method
* separately if you need something more specific (like activating logging or
* putting a timeout).
*
* @param errorMessage the expected error message
* @return the {@link Duration} of the verification
*
* @see #expectErrorMessage(String)
* @see #verify()
* @see Subscriber#onError(Throwable)
*/
Duration verifyErrorMessage(String errorMessage);
/**
* Trigger the {@link #verify() verification}, expecting an error that matches
* the given predicate as terminal event.
*
* This is a convenience method that calls {@link #verify()} in addition to the
* expectation. Explicitly use the expect method and verification method
* separately if you need something more specific (like activating logging or
* putting a timeout).
*
* @param predicate the predicate to test on the next received error
* @return the {@link Duration} of the verification
*
* @see #expectErrorMatches(Predicate)
* @see #verify()
* @see Subscriber#onError(Throwable)
*/
Duration verifyErrorMatches(Predicate predicate);
/**
* Trigger the {@link #verify() verification}, expecting a completion signal
* as terminal event.
*
* This is a convenience method that calls {@link #verify()} in addition to the
* expectation. Explicitly use the expect method and verification method
* separately if you need something more specific (like activating logging or
* putting a timeout).
*
* @return the {@link Duration} of the verification
*
* @see #expectComplete()
* @see #verify()
* @see Subscriber#onComplete()
*
*/
Duration verifyComplete();
}
/**
* Define a builder for expecting main sequence individual signals.
*
* @param the type of values that the subscriber contains
*/
interface Step extends LastStep {
/**
* Set a description for the previous verification step. Choosing
* a unique and descriptive name can make assertion errors easier to
* resolve.
*
* Note that calling this several times in a row will only take the
* first description into account.
*
* @param description the description for the previous verification step
* @return this builder
*/
Step as(String description);
/**
* Expect an element and consume with the given consumer. Any {@code
* AssertionError}s thrown by the consumer will be rethrown during {@linkplain
* #verify() verification}.
*
* @param consumer the consumer for the value
*
* @return this builder
*/
Step consumeNextWith(Consumer super T> consumer);
/**
* Expect an element and consume it with the given consumer, usually performing
* assertions on it (eg. using Hamcrest, AssertJ or JUnit assertion methods).
* Alias for {@link #consumeNextWith(Consumer)} for better discoverability of
* that use case.
*
* Any {@code AssertionError}s thrown by the consumer will be rethrown during
* {@linkplain #verify() verification}.
*
* @param assertionConsumer the consumer for the value, performing assertions
* @return this builder
*/
default Step assertNext(Consumer super T> assertionConsumer) {
return consumeNextWith(assertionConsumer);
}
/**
* Expect a recording session started via {@link #recordWith} and
* consume with
* the
* given consumer. Any {@code
* AssertionError}s thrown by the consumer will be rethrown during {@linkplain
* #verify() verification}.
*
* @param consumer the consumer for the value
*
* @return this builder
*/
Step consumeRecordedWith(Consumer super Collection> consumer);
/**
* Expect the next elements received to be equal to the given values.
*
* @param ts the values to expect
*
* @return this builder
*
* @see Subscriber#onNext(Object)
*/
Step expectNext(T... ts);
/**
* Expect an element count starting from the last expectation or onSubscribe.
*
* @param count the predicate to test on the next received value
*
* @return this builder
*
* @see Subscriber#onNext(Object)
*/
Step expectNextCount(long count);
/**
* Expect the next elements to match the given {@link Iterable} until its
* iterator depletes.
*
* @param iterable the predicate to test on the next received value
*
* @return this builder
*
* @see Subscriber#onNext(Object)
*/
Step expectNextSequence(Iterable extends T> iterable);
/**
* Expect an element and evaluate with the given predicate.
*
* @param predicate the predicate to test on the next received value
*
* @return this builder
*
* @see Subscriber#onNext(Object)
*/
Step expectNextMatches(Predicate super T> predicate);
/**
* Expect a {@link Subscription} and consume with the given consumer. Any {@code
* AssertionError}s thrown by the consumer will be rethrown during {@linkplain
* #verify() verification}.
*
* @param consumer the consumer for the {@link Subscription}
*
* @return this builder
*
* @see Subscriber#onSubscribe(Subscription)
*/
Step consumeSubscriptionWith(Consumer super Subscription> consumer);
/**
* Expect that no event has been observed by the verifier. A duration is
* necessary to limit in time that "nothing" has effectively happened.
*
* @param duration the period to observe no event has been received
*
* @return this builder
*
* @see Subscriber
*/
Step expectNoEvent(Duration duration);
/**
* Expect and end a recording session started via {@link #recordWith} and
* consume with
* the
* given consumer.
*
* @param predicate the predicate to test on the recorded session
*
* @return this builder
*
* @see Subscriber#onNext(Object)
*/
Step expectRecordedMatches(Predicate super Collection> predicate);
/**
* Start a recording session storing {@link Subscriber#onNext(Object)} values in
* the
* supplied {@link Collection}. Further steps
* {@link #expectRecordedMatches(Predicate)} and
* {@link #consumeRecordedWith(Consumer)} can consume the session.
* If an
* existing recording session hasn't not been declaratively consumed, this step
* will override the current session.
*
* @param supplier the task to run
*
* @return this builder
*/
Step recordWith(Supplier extends Collection> supplier);
/**
* Run an arbitrary task scheduled after previous expectations or tasks.
*
* @param task the task to run
*
* @return this builder
*/
Step then(Runnable task);
/**
* Mark a Pause in the expectation evaluation.
* If a {@link VirtualTimeScheduler} has been configured,
* {@link VirtualTimeScheduler#advanceTime()} will be used and the
* pause will not block testing or {@link Publisher} thread.
*
* @return this builder
*/
default Step thenAwait() {
return thenAwait(Duration.ZERO);
}
/**
* Pause the expectation evaluation for a given {@link Duration}.
* If a {@link VirtualTimeScheduler} has been configured,
* {@link VirtualTimeScheduler#advanceTimeBy(Duration)} will be used and the
* pause will not block testing or {@link Publisher} thread.
*
* @param timeshift a pause {@link Duration}
*
* @return this builder
*/
Step thenAwait(Duration timeshift);
/**
* Consume further onNext signals as long as they match a predicate.
*
* @param predicate the condition to continue consuming onNext
*
* @return this builder
*/
Step thenConsumeWhile(Predicate predicate);
/**
* Consume further onNext signals using a provided {@link Consumer} as long as
* they match a {@link Predicate}.
*
* @param predicate the condition to continue consuming onNext
* @param consumer the consumer to use to consume the data, when the predicate
* matches
*
* @return this builder
*/
Step thenConsumeWhile(Predicate predicate, Consumer consumer);
/**
* Request the given amount of elements from the upstream {@code Publisher}. This
* is in addition to the initial number of elements requested by an
* initial passed demand like with {@link StepVerifier#create(Publisher, long)}.
*
* @param n the number of elements to request
*
* @return this builder
*
* @see Subscription#request(long)
*/
Step thenRequest(long n);
}
/**
* Define a builder for explicitly expecting an initializing {@link Subscription} as
* first signal.
*
* If {@link FirstStep} expectations are not used, the produced
* {@link StepVerifier} keeps a first expectation that will be checking if
* the first signal is a
* {@link Subscription}.
*
* @param the type of values that the subscriber contains
*/
interface FirstStep extends Step {
/**
* Expect the source {@link Publisher} to run with Reactor Fusion flow
* optimization. It will be requesting {@link Fuseable#ANY} fusion mode.
*
* @return this builder
*
* @see Fuseable
*/
Step expectFusion();
/**
* Expect the source {@link Publisher} to run the requested Reactor Fusion mode
* from any of these modes :
* {@link Fuseable#NONE}, {@link Fuseable#SYNC}, {@link Fuseable#ASYNC},
* {@link Fuseable#ANY}, {@link Fuseable#THREAD_BARRIER}.
*
* @param requested the requested and expected fusion mode
*
* @return this builder
*
* @see Fuseable
*/
Step expectFusion(int requested);
/**
* Expect the source {@link Publisher} to run with Reactor Fusion flow
* optimization.
* Expect the source {@link Publisher} to run the requested Reactor Fusion mode
* from any of these modes :
* {@link Fuseable#NONE}, {@link Fuseable#SYNC}, {@link Fuseable#ASYNC},
* {@link Fuseable#ANY}, {@link Fuseable#THREAD_BARRIER}.
*
* @param requested the requested fusion mode
* @param expected the expected fusion mode
*
* @return this builder
*
* @see Fuseable
*/
Step expectFusion(int requested, int expected);
/**
* Expect the source {@link Publisher} to NOT run with Reactor Fusion flow
* optimization. It will check if publisher is {@link Fuseable} or
* subscription is a {@link Fuseable.QueueSubscription}.
*
* @return this builder
*
* @see Fuseable
*/
Step expectNoFusionSupport();
/**
* Expect no Subscription or any other event for the given duration.
*
* @param duration the period to observe no event has been received
*
* @return this builder
*/
@Override
FirstStep expectNoEvent(Duration duration);
/**
* Expect a {@link Subscription}.
* Effectively behave as the default implicit {@link Subscription} expectation.
*
* @return this builder
*
* @see Subscriber#onSubscribe(Subscription)
*/
Step expectSubscription();
/**
* Expect a {@link Subscription} and evaluate with the given predicate.
*
* @param predicate the predicate to test on the received {@link Subscription}
*
* @return this builder
*
* @see Subscriber#onSubscribe(Subscription)
*/
Step expectSubscriptionMatches(Predicate super Subscription> predicate);
}
/**
* Exposes post-verification state assertions.
*/
interface Assertions {
/**
* Assert that the tested publisher has dropped at least one element to the
* {@link Hooks#onNextDropped(Consumer)} hook.
*/
Assertions hasDroppedElements();
/**
* Assert that the tested publisher has dropped at least all of the provided
* elements to the {@link Hooks#onNextDropped(Consumer)} hook, in any order.
*/
Assertions hasDropped(Object... values);
/**
* Assert that the tested publisher has dropped all of the provided elements to
* the {@link Hooks#onNextDropped(Consumer)} hook, in any order, and that no
* other elements were dropped.
*/
Assertions hasDroppedExactly(Object... values);
/**
* Assert that the tested publisher has dropped at least one error to the
* {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrors();
/**
* Assert that the tested publisher has dropped exactly n errors to the
* {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrors(int n);
/**
* Assert that the tested publisher has dropped exactly one error of the given type
* to the {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrorOfType(Class extends Throwable> clazz);
/**
* Assert that the tested publisher has dropped exactly one error matching the given
* predicate to the {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrorMatching(Predicate matcher);
/**
* Assert that the tested publisher has dropped exactly one error with the exact provided
* message to the {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrorWithMessage(String message);
/**
* Assert that the tested publisher has dropped exactly one error with a message containing
* the provided string to the {@link Hooks#onErrorDropped(Consumer)} hook.
*/
Assertions hasDroppedErrorWithMessageContaining(String messagePart);
/**
* Assert that the tested publisher has dropped one or more errors to the
* {@link Hooks#onErrorDropped(Consumer)} hook, and assert them as a collection.
*/
Assertions hasDroppedErrorsSatisfying(Consumer> errorsConsumer);
/**
* Assert that the tested publisher has dropped one or more errors to the
* {@link Hooks#onErrorDropped(Consumer)} hook, and check that the collection of
* errors matches a predicate.
*/
Assertions hasDroppedErrorsMatching(Predicate> errorsConsumer);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* at least once.
*/
Assertions hasOperatorErrors();
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* exactly n times.
*/
Assertions hasOperatorErrors(int n);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* exactly once and the error is of the given type.
*/
Assertions hasOperatorErrorOfType(Class extends Throwable> clazz);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* exactly once and the error matches the given predicate.
*/
Assertions hasOperatorErrorMatching(Predicate matcher);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* exactly once and the error has the exact provided message.
*/
Assertions hasOperatorErrorWithMessage(String message);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* exactly once, with the error message containing the provided string.
*/
Assertions hasOperatorErrorWithMessageContaining(String messagePart);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* once or more, and assert the errors and optionally associated data as a collection.
*/
Assertions hasOperatorErrorsSatisfying(Consumer>> errorsConsumer);
/**
* Assert that the tested publisher has triggered the {@link Hooks#onOperatorError(BiFunction) onOperatorError} hook
* once or more, and check that the collection of errors and their optionally
* associated data matches a predicate.
*/
Assertions hasOperatorErrorsMatching(Predicate>> errorsConsumer);
/**
* Assert that the whole verification took strictly less than the provided
* duration to execute.
* @param d the expected maximum duration of the verification
*/
Assertions tookLessThan(Duration d);
/**
* Assert that the whole verification took strictly more than the provided
* duration to execute.
* @param d the expected minimum duration of the verification
*/
Assertions tookMoreThan(Duration d);
}
}