FeatureRequest: I wish there is a SoftAssertions.assertThat().isNotNullAndSatisfies( Consumer )
Summary
When I want to verify fields in a nested object structure, SoftAssertions are cool, because they print out everything and do not stop on the first error. However, when i access a field that can be null and want to go deeper, I need to write the field access twice or have a variable and "if". Non-fluent calls with repeating symbols:
var something = obj.getSomething();
softly.assertThat( something ).isNotNull();
if( something != null ){
softly.assertthat(something.other()) ...; // (1)
}
... more tests on obj ...
The "if" is to avoid, when "something" is null, that it throws NPE in (1) and stops printing the remaining stuff. The normal satisfies() does not check for isNotNull(), and even when .isNotNull() is chained with satisfies() as the consumer is called. Hence the access will throw NPE.
Example
A workaround:
public static <T> Consumer<T> notNullFilter(final Consumer<T> consumer) {
return t -> {
if (t != null) {
consumer.accept(t);
}
};
}
softly.assertThat( obj.getSomething() )
.isNotNull()
.satisfies( notNullFilter( something -> {
softly.assertThat(something.other())
.isEqualTo("x12");
}));
softly.assertThat("asd")
.isEqualTo("xxx");
That is near to what I want, but if the .isNotNull() call is forgotten, the block is silently not tested.
So I wish there would be a isNotNullAndSatisfies( Consumer<T> ), which does the isNotNull() and only calls the consumer if the object is non-null:
softly.assertThat( obj.getSomething() )
.isNotNullAndSatisfies( something -> {
softly.assertThat(something.other())
.isEqualTo("x12");
});
softly.assertThat("asd")
.isEqualTo("xxx");
I'm not sure I understand where the problem is. Would you mind providing a reproducible example?
My request only makes sense for soft assertions. Here, after a failed expectation, further assertions shall be evaluated and printed.
The above example, obj is exercised and as well the returned value from getSomething().
In the error case, that getSomething() returns null, this shall be detected as an error, but the assertions on that returned null shall not be evaluated, because this would cause an NPE to be thrown.
But independently of the returned value is null or not, the following assertions on obj shall be executed.
- assert a value is non null
- call a consumer only in case of non null (only relevant for soft-assertions, because they continue after an assertion failure)
Hi @scordio, under my understanding Frank might want AbstractObjectAssert#isNotNullAndSatisfies as a shortcut for both check not null and check the requirement, something like:
@SafeVarargs
public final SELF isNotNullAndSatisfies(Consumer<? super ACTUAL>... requirements) {
isNotNull();
satisfies(requirements);
return myself;
}
(@frankbenoit please also check if this is what you mean) is that okay for adding it? If so, I'll be glad to work on it.
@HeZean sorry, this is not yet up for grabs, I suggest keeping an eye on the good first issues.
I guess this is a more generic variation of the feature, however isNotNullAndSatisfies might indeed be helpful:
- https://github.com/assertj/assertj/issues/2914