-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce assorted Reactor StepVerifier
Refaster rules
#1132
base: master
Are you sure you want to change the base?
Conversation
Looks good. No mutations were possible for these changes. |
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} with AssertJ over more | ||
* contrived alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorSatisfiesAssertJ { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Class<? extends Throwable> clazz, String message) { | ||
Refaster.anyOf( | ||
step.expectError() | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(clazz) | ||
.hasOperatorErrorWithMessage(message), | ||
step.expectError(clazz).verifyThenAssertThat().hasOperatorErrorWithMessage(message), | ||
step.expectErrorMessage(message).verifyThenAssertThat().hasOperatorErrorOfType(clazz)); | ||
} | ||
|
||
@AfterTemplate | ||
@UseImportPolicy(STATIC_IMPORT_ALWAYS) | ||
void after(StepVerifier.LastStep step, Class<? extends Throwable> clazz, String message) { | ||
step.verifyErrorSatisfies( | ||
t -> Assertions.assertThat(t).isInstanceOf(clazz).hasMessage(message)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asserting both class and message blocks one to use the recommended StepVerifier.Step#verifyError(Class)
or StepVerifier.Step#verifyErrorMessage(String)
. Choosing an alternative isn't easy since there are many possibilities. Out of all the options, AssertJ's assertions have the richest API, so I'd recommend this.
The StepVerifierVerify
rule introduced in this PR aims to rewrite the use-cases in which only one of class or message are asserted by dropping the StepVerifier.Assertions
type which allows other rules to rewrite further.
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorMatches(Predicate)} over more verbose | ||
* alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorMatchesAssertions { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate); | ||
} | ||
|
||
@AfterTemplate | ||
void after(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.verifyErrorMatches(predicate); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is not exhaustive due to the overload of StepVerifier.LastStep#expectedError
, but IMO covers sufficiently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can collapse this one into the preceding method.
/** Don't unnecessarily invoke {@link StepVerifier#verifyLater()} multiple times. */ | ||
static final class StepVerifierVerifyLater<T> { | ||
@BeforeTemplate | ||
StepVerifier before(StepVerifier stepVerifier) { | ||
return stepVerifier.verifyLater().verifyLater(); | ||
} | ||
|
||
@AfterTemplate | ||
StepVerifier after(StepVerifier stepVerifier) { | ||
return stepVerifier.verifyLater(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API spec mentions this is a noop. I didn't fully understand why this API may be useful for in the first place.
7395f93
to
0eea3ac
Compare
Looks good. No mutations were possible for these changes. |
1 similar comment
Looks good. No mutations were possible for these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a commit. Tnx @werli!
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorMatches(Predicate)} over more verbose | ||
* alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorMatchesAssertions { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate); | ||
} | ||
|
||
@AfterTemplate | ||
void after(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.verifyErrorMatches(predicate); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can collapse this one into the preceding method.
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectError() | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(IllegalStateException.class) | ||
.hasOperatorErrorWithMessage("foo"); | ||
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectError(IllegalStateException.class) | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorWithMessage("bar"); | ||
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectErrorMessage("baz") | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(IllegalStateException.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use three different Throwable
types like a bit further up.
*/ | ||
static final class StepVerifierVerify { | ||
@BeforeTemplate | ||
void before(StepVerifier stepVerifier) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While in this case arguably incorrect, we do generally match any expression, even if that can lead to compilation errors. (At least this will force the user to clean up the code.)
I'll apply those changes to this PR, though I could also see us change our mind on that in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intent was indeed to avoid breaking code changes by only matching the "dangling" case in which the created StepVerifier.Assertions
isn't used or cases we should clearly rewrite.
StepVerifier#verifyThenAssertThat
has some valid yet niche usages, see internal usages. Sure, we could suppress the warning here, but IMO the warning would be a false positive. WDYT?
Looks good. No mutations were possible for these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice improvements!
3742218
to
fcbda80
Compare
Looks good. No mutations were possible for these changes. |
Quality Gate passedIssues Measures |
Summary
This PR introduces a bunch of rules associated to
StepVerifier.Asserations
and a trivialStepVerifier
rule.Example
I spotted the following interesting pattern:
Which made me find the interesting
StepVerifier#Assertions
API. It's quite low-level, and IMO not as straightforward to read and write.The example itself is most often represented in our code-base using AssertJ's richer API:
Suggested commit message: