StepVerifier: *LastStep issues with cancellation and terminal events
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1k
- Forks
- 230
- Avg merge
- 23h 23m
- Merged PRs (30d)
- 16
Description
thenCancel() is on the *LastStep interface, but it triggers cancellation right away ignoring all previous steps.
Example:
@Test
public void requesterPayloadBodyDoesNotTimeoutWhenIgnored() {
Duration timeout = ofMillis(100L);
TestPublisher<Buffer> payloadBody = new TestPublisher<>();
FilterableStreamingHttpConnection connection = connection(succeeded(newResponse(payloadBody)));
StreamingHttpRequester requester = new TimeoutHttpRequesterFilter(timeout, false).create(connection);
AtomicBoolean responseSucceeded = new AtomicBoolean();
StepVerifiers.create(requester.request(STRATEGY, mock(StreamingHttpRequest.class))
.whenOnSuccess(__ -> responseSucceeded.set(true))
.whenCancel(() -> System.out.println("CANCELLED"))
.flatMapPublisher(StreamingHttpResponse::payloadBody))
.thenRequest(MAX_VALUE)
.expectNoSignals(timeout.plusMillis(10L))
.thenCancel()
.verify();
assertThat("Response did not succeeded", responseSucceeded.get(), is(true));
assertThat("No subscribe for payload body", payloadBody.isSubscribed(), is(true));
}
This test is expected to cancel after "expectNoSignals", but it cancels immediately.
The workaround is to intercept the Cancellable manually, schedule cancellation using executor, and use another terminal state. Example:
AtomicReference<Cancellable> cancellable = new AtomicReference<>();
stepVerifier(requester.request(...)
.expectCancellableConsumed(cancellable::set)
.then(() -> {
try {
secondRequestReceivedLatch.await();
cancellable.get().cancel(); // If I use thenCancel() the current then(Runnable) does not run
} catch (InterruptedException e) {
// ignore
}
})
.expectError() // subscrived.onError(…) was never invoked, test is green
.verify();
This is confusing because expectError is just ignored. It's only there to transition to verify() method through the last step.
thenCancel() should trigger cancellation only after all previous steps complete. Or we should have another step method that will have described behavior.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the StepVerifier *LastStep.thenCancel() entry point and reproduce the behavior with the requesterPayloadBodyDoesNotTimeoutWhenIgnored() test shown in the issue. Check that preceding steps, including expectNoSignals(timeout), complete before cancellation; done when the test cancels only afterward and the existing terminal-step behavior remains covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100