Interface TestSubscriber<T>
- All Superinterfaces:
CoreSubscriber<T>,Scannable,Subscriber<T>
- All Known Subinterfaces:
ConditionalTestSubscriber<T>
CoreSubscriber that can be attached to any Publisher to later assert which
events occurred at runtime. This can be used as an alternative to StepVerifier
for more complex scenarios, e.g. more than one possible outcome, racing...
The subscriber can be fine tuned with a builder(), which also allows to produce a Fuseable.ConditionalSubscriber
variant if needed.
Subscriber-inherited methods never throw, but a few failure conditions might be met, which
fall into two categories.
The first category are "protocol errors": when the occurrence of an incoming signal doesn't follow the Reactive Streams
specification. The case must be covered explicitly in the specification, and leads to the signal being added to the
getProtocolErrors() list. All protocol errors imply that the Publisher has terminated
already. The list of detected protocol errors is:
- the
TestSubscriberhas already terminated (onComplete or onError), but anSubscriber.onNext(Object)is received: onNext signal added to protocol errors - the
TestSubscriberhas already terminated, but anSubscriber.onComplete()is received: onComplete signal added to protocol errors - the
TestSubscriberhas already terminated, but anSubscriber.onError(Throwable)is received: onError signal added to protocol errors
The second category are "subscription failures", which are the only ones for which TestSubscriber internally performs an assertion.
These failure conditions always lead to a cancellation of the subscription and are represented as an AssertionError.
The assertion error is thrown by all the getXxx and isXxx accessors, the block() methods
and the expectTerminalError()/expectTerminalSignal() methods. The possible subscription failures are:
- the
TestSubscriberhas already received aSubscription(ie. it is being reused). Both subscriptions are cancelled. - the incoming
Subscriptionis not capable of fusion, but fusion was required by the user - the incoming
Subscriptionis capable of fusion, but this was forbidden by the user - the incoming
Subscriptionis capable of fusion, but the negotiated fusion mode is not the one required by the user - onNext(null) is received, which should denote ASYNC fusion, but ASYNC fusion hasn't been established
- Author:
- Simon Baslé
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic enumAn enum representing the 3 broad expectations around fusion.Nested classes/interfaces inherited from interface reactor.core.Scannable
Scannable.Attr<T extends Object> -
Field Summary
Fields inherited from interface reactor.core.Scannable
OPERATOR_NAME_UNRELATED_WORDS_PATTERN -
Method Summary
Modifier and TypeMethodDescriptionvoidblock()Block until an assertable end state has been reached.voidBlock until an assertable end state has been reached, or a timeoutDurationhas elapsed.static TestSubscriberBuilderbuilder()Create aTestSubscriberwith tuning.voidcancel()static <T> TestSubscriber<T>create()Create a simple plainTestSubscriberwhich will make an unbounded demandon subscription, has an emptyContextand makes no attempt at fusion negotiation.Expect theTestSubscriberto beterminatedwith anSubscriber.onError(Throwable)and return the terminatingThrowableif so.intReturn anintcode that represents the negotiated fusion mode for thisTestSubscriber.Return aListofSignalwhich represent detected protocol error from the sourcePublisher, that is to say signals that were emitted to thisTestSubscriberin violation of the Reactive Streams specification.Return theListof all elements that have correctly been emitted to theTestSubscriber(onNext signals) so far.Return theListof elements that have been emitted to theTestSubscriber(onNext signals) so far, after acancel()was triggered.booleanCheck if thisTestSubscriberhas beencancelled, which impliesisTerminatedOrCancelled()is also true.booleanCheck if thisTestSubscriberhas received a terminal signal, ie.booleanCheck if thisTestSubscriberhas received a terminal signal that is specifically onComplete.booleanCheck if thisTestSubscriberhas received a terminal signal that is specifically onError.booleanCheck if thisTestSubscriberhas either: been cancelled:isCancelled()would return true been terminated, having been signalled with onComplete or onError:isTerminated()would return true andgetTerminalSignal()would return a non-nullSignalThe third possible failure condition, subscription failure, results in anAssertionErrorbeing thrown by this method (like all other accessors, see alsoTestSubscriberjavadoc).voidrequest(long n) Methods inherited from interface reactor.core.CoreSubscriber
currentContext, onSubscribeMethods inherited from interface reactor.core.Scannable
actuals, inners, isScanAvailable, name, parents, scan, scanOrDefault, scanUnsafe, stepName, steps, tags, tagsDeduplicatedMethods inherited from interface org.reactivestreams.Subscriber
onComplete, onError, onNext
-
Method Details
-
create
Create a simple plainTestSubscriberwhich will make an unbounded demandon subscription, has an emptyContextand makes no attempt at fusion negotiation.- Type Parameters:
T- the type of data received by this subscriber- Returns:
- a new plain
TestSubscriber
-
builder
Create aTestSubscriberwith tuning. SeeTestSubscriberBuilder.- Returns:
- a
TestSubscriberBuilderto fine tune theTestSubscriberto produce
-
cancel
void cancel() -
request
void request(long n) Requestnelements from thePublisher'sSubscription. If this method is called before theTestSubscriberhas subscribed to thePublisher, pre-request is accumulated (includingconfigured initial requestand replayed in a single batch upon subscription.Note that if/once
Fuseable.SYNCfusion mode is established, this method MUST NOT be used, and this will throw anIllegalStateException.- Parameters:
n- the additional amount to request
-
isTerminatedOrCancelled
boolean isTerminatedOrCancelled()Check if thisTestSubscriberhas either:- been cancelled:
isCancelled()would return true - been terminated, having been signalled with onComplete or onError:
isTerminated()would return true andgetTerminalSignal()would return a non-nullSignal
AssertionErrorbeing thrown by this method (like all other accessors, see alsoTestSubscriberjavadoc).Once this method starts returning true, any pending
block()calls should finish, and subsequent block calls will return immediately.- Returns:
- true if the
TestSubscriberhas reached an end state - Throws:
AssertionError- in case of failure at subscription time
- been cancelled:
-
isTerminated
boolean isTerminated()Check if thisTestSubscriberhas received a terminal signal, ie. onComplete or onError. When returningtrue, implies:isTerminatedOrCancelled()is also truegetTerminalSignal()returns a non-nullSignalexpectTerminalSignal()} returns theSignalexpectTerminalError()} returns theSignalin case of onError but throws in case of onComplete
- Returns:
- true if the
TestSubscriberhas been terminated via onComplete or onError - Throws:
AssertionError- in case of failure at subscription time
-
isTerminatedComplete
boolean isTerminatedComplete()Check if thisTestSubscriberhas received a terminal signal that is specifically onComplete. When returningtrue, implies:isTerminatedOrCancelled()is also trueisTerminated()is also truegetTerminalSignal()returns a non-null onCompleteSignalexpectTerminalSignal()} returns the same onCompleteSignalexpectTerminalError()} throws
- Returns:
- true if the
TestSubscriberhas been terminated via onComplete - Throws:
AssertionError- in case of failure at subscription time
-
isTerminatedError
boolean isTerminatedError()Check if thisTestSubscriberhas received a terminal signal that is specifically onError. When returningtrue, implies:isTerminatedOrCancelled()is also trueisTerminated()is also truegetTerminalSignal()returns a non-null onErrorSignalexpectTerminalSignal()} returns the same onErrorSignalexpectTerminalError()} returns the terminatingThrowable
- Returns:
- true if the
TestSubscriberhas been terminated via onComplete - Throws:
AssertionError- in case of failure at subscription time
-
isCancelled
boolean isCancelled()Check if thisTestSubscriberhas beencancelled, which impliesisTerminatedOrCancelled()is also true.- Returns:
- true if the
TestSubscriberhas been cancelled - Throws:
AssertionError- in case of failure at subscription time
-
getTerminalSignal
Return the terminalSignalif thisTestSubscriberisTerminated(), ornullotherwise. See alsoexpectTerminalSignal()as a stricter way of asserting the terminal state.- Returns:
- the terminal
Signalor null if not terminated - Throws:
AssertionError- in case of failure at subscription time- See Also:
-
expectTerminalSignal
Expect theTestSubscriberto beterminated, and return the terminalSignalif so. Otherwise, cancel the subscription and throw anAssertionError.Note that is there was already a subscription failure, the corresponding
AssertionErroris raised by this method instead.- Returns:
- the terminal
Signal(cannot be null) - Throws:
AssertionError- in case of failure at subscription time, or if the subscriber hasn't terminated yet- See Also:
-
expectTerminalError
Throwable expectTerminalError()Expect theTestSubscriberto beterminatedwith anSubscriber.onError(Throwable)and return the terminatingThrowableif so. Otherwise, cancel the subscription and throw anAssertionError.- Returns:
- the terminal
Throwable(cannot be null) - Throws:
AssertionError- in case of failure at subscription time, or if the subscriber hasn't errored.- See Also:
-
getReceivedOnNext
Return theListof all elements that have correctly been emitted to theTestSubscriber(onNext signals) so far. This returns a new list that is not backed by theTestSubscriber.Note that this includes elements that would arrive after
cancel(), as this is allowed by the Reactive Streams specification (cancellation is not necessarily synchronous and some elements may already be in flight when the source takes notice of the cancellation). These elements are also mirrored in thegetReceivedOnNextAfterCancellation()getter.- Returns:
- the
Listof all elements received by theTestSubscriberas part of normal operation - Throws:
AssertionError- in case of failure at subscription time- See Also:
-
getReceivedOnNextAfterCancellation
Return theListof elements that have been emitted to theTestSubscriber(onNext signals) so far, after acancel()was triggered. This returns a new list that is not backed by theTestSubscriber.Note that this is allowed by the Reactive Streams specification (cancellation is not necessarily synchronous and some elements may already be in flight when the source takes notice of the cancellation). This is a sub-list of the one returned by
getReceivedOnNext()(in the conceptual sense, as the two lists are independent copies).- Returns:
- the
Listof elements ofgetReceivedOnNext()that were received by theTestSubscriberaftercancel()was triggered - Throws:
AssertionError- in case of failure at subscription time- See Also:
-
getProtocolErrors
Return aListofSignalwhich represent detected protocol error from the sourcePublisher, that is to say signals that were emitted to thisTestSubscriberin violation of the Reactive Streams specification. An example would be anSubscriber.onNext(Object)signal emitted after anSubscriber.onComplete()signal.Note that the
Signalin the collection don't bear anyContextView, since they would all be the configuredCoreSubscriber.currentContext().- Returns:
- a
ListofSignalrepresenting the detected protocol errors from the sourcePublisher - Throws:
AssertionError- in case of failure at subscription time
-
getFusionMode
int getFusionMode()Return anintcode that represents the negotiated fusion mode for thisTestSubscriber. Fusion codes can be converted to a human-readable value for display viaFuseable.fusionModeName(int). If no particular fusion has been requested, returnsFuseable.NONE. Note that as long as thisTestSubscriberhasn't been subscribed to aPublisher, this method will return-1. It will also throw anAssertionErrorif the configured fusion mode couldn't be negotiated at subscription.- Returns:
- -1 if not subscribed, 0 (
Fuseable.NONE) if no fusion negotiated, a relevant fusion code otherwise - Throws:
AssertionError- in case of failure at subscription time
-
block
void block()Block until an assertable end state has been reached. This can be either a cancellation (isCancelled()), a "normal" termination (isTerminated()) or subscription failure. In the later case only, this method throws the correspondingAssertionError.An AssertionError is also thrown if the thread is interrupted.
- Throws:
AssertionError- in case of failure at subscription time (or thread interruption)
-
block
Block until an assertable end state has been reached, or a timeoutDurationhas elapsed. End state can be either a cancellation (isCancelled()), a "normal" termination (isTerminated()) or a subscription failure. In the later case only, this method throws the correspondingAssertionError. In case of timeout, anAssertionErrorwith a message reflecting the configured duration is thrown.An AssertionError is also thrown if the thread is interrupted.
- Throws:
AssertionError- in case of failure at subscription time (or thread interruption)
-