Repository navigation
Inspecting Violations
These assertions take what validation already produced. They do not extend AbstractValidationAssert: there is
nothing left to validate, so they have no usingValidator or targetingGroups.
The examples assume a validator obtained from a ValidatorFactory the test keeps open (see
Validator Lifecycle), or the sets handed to a consumer by the validation assertions.
| Entry point | Returns |
|---|---|
assertThatConstraintViolations(Set<? extends ConstraintViolation<T>>) |
AbstractIterableOfConstraintViolationsAssert<?, T> |
assertThatIterableOfConstraintViolations(Iterable<? extends ConstraintViolation<T>>) |
the same type |
The first takes the Set that validate, validateProperty and validateValue return; it delegates to the second.
The assertion is an AssertJ AbstractIterableAssert, so the whole iterable vocabulary is there — hasSize,
isEmpty, allSatisfy, extracting, filteredOn, first, singleElement, element(int) and the rest. Its element
assertion is the constraint-violation assertion below, and a filtered result is again a violation-set assertion, so
navigation stays typed after filteredOn:
final Set<ConstraintViolation<User>> violations = validator.validate(new User(null, -1));
assertThatConstraintViolations(violations)
.hasSize(2)
.filteredOn(v -> v.getPropertyPath().toString().equals("name"))
.hasSize(1)
.first()
.hasMessageTemplate("{jakarta.validation.constraints.NotBlank.message}");
assertThatConstraintViolations(violations)
.isNotEmpty()
.allSatisfy(v -> assertThat(v.getMessage()).isNotBlank());There are no violation-specific shortcuts on the set yet, such as "has a violation on name"; those are proposed in
#13. Today it is filteredOn / extracting with a lambda.
assertThatConstraintViolation(ConstraintViolation<T>) returns an
AbstractConstraintViolationAssert<?, ConstraintViolation<T>, T>. Each property of ConstraintViolation has an
extracting… method returning an assertion for it, and most have a direct has… check.
| Property | Extract | Check |
|---|---|---|
getMessage() |
— | hasMessage(String) |
getMessageTemplate() |
extractingMessageTemplate(), extractingMessageTemplate(AssertFactory)
|
hasMessageTemplate(String) |
getRootBean() |
extractingRootBean(), extractingRootBean(AssertFactory)
|
hasRootBean(T), doesNotHaveRootBean()
|
getRootBeanClass() |
extractingRootBeanClass(), extractingRootBeanClass(AssertFactory)
|
hasRootBeanClass(Class<T>) |
getLeafBean() |
extractingLeafBean(), extractingLeafBean(AssertFactory), extractingLeafBean(Function, AssertFactory)
|
hasLeafBean(Object), doesNotHaveLeafBean()
|
getInvalidValue() |
extractingInvalidValue(), extractingInvalidValue(Function, AssertFactory)
|
hasInvalidValue(Object) |
getPropertyPath() |
extractingPropertyPath(), extractingPropertyPath(AssertFactory)
|
— see Paths and Nodes |
getConstraintDescriptor() |
extractingConstraintDescriptor(), extractingConstraintDescriptor(Function, AssertFactory)
|
— see Metadata |
getExecutableParameters() |
extractingExecutableParameters(), extractingExecutableParameters(Function, AssertFactory)
|
hasExecutableParameters(Object[]), hasNoExecutableParameters()
|
getExecutableReturnValue() |
extractingExecutableReturnValue(), extractingExecutableReturnValue(Function, AssertFactory)
|
hasExecutableReturnValue(Object), hasNoExecutableReturnValue()
|
unwrap(Class) |
extractingAsUnwrapped(Class, AssertFactory) |
isEqualToWhenUnwrappedAs(Class, Object) |
hasRootBeanClass rejects a null argument with a NullPointerException. The doesNotHave… / hasNo… methods
are the corresponding has… with null.
hasMessage(String) asserts the interpolated message, which depends on the default locale and on any
MessageInterpolator. hasMessageTemplate(String) asserts the raw template as declared, which does not:
final ConstraintViolation<User> violation =
validator.validateValue(User.class, "name", null).iterator().next();
assertThatConstraintViolation(violation)
.hasMessageTemplate("{jakarta.validation.constraints.NotBlank.message}");
assertThatConstraintViolation(violation)
.extractingMessageTemplate()
.startsWith("{")
.endsWith("}");Prefer the template unless the interpolated text is what is under test.
What these hold depends on which Validator method produced the violation. For validateValue there is no
instance, so root and leaf bean are null and only the class is known — User_ConstraintViolationAssert_Test
checks exactly this:
final var name = " ";
final ConstraintViolation<User> cv =
validator.validateValue(User.class, "name", name).iterator().next();
assertThatConstraintViolation(cv)
.hasNoExecutableParameters()
.hasNoExecutableReturnValue()
.hasInvalidValue(name)
.doesNotHaveLeafBean()
.doesNotHaveRootBean()
.hasRootBeanClass(User.class);
assertThatConstraintViolation(cv)
.extractingConstraintDescriptor()
.extractingAnnotation()
.isInstanceOf(NotBlank.class);For validate(bean) the root bean is the validated instance, so hasRootBean(bean) applies.
assertThatConstraintViolation(cv)
.extractingPropertyPath()
.hasSize(1)
.hasNodeSatisfying(0, node -> node
.hasKind(ElementKind.PROPERTY)
.hasName("name")
.doesNotHaveIndex()
.isNotInIterable());See Paths and Nodes.
assertThatConstraintViolationException(ConstraintViolationException) is for the exception a framework throws when
it, rather than the test, triggers validation. Not in 0.6.1.
It extends AssertJ's AbstractThrowableAssert, so hasMessage, hasCause and the rest are available, and adds:
| Method | |
|---|---|
hasViolationOn(String expectedPropertyPath) |
passes when at least one violation's getPropertyPath().toString() equals the argument |
extractingConstraintViolations() |
a CollectionAssert<ConstraintViolation<?>> of getConstraintViolations()
|
assertThatConstraintViolationException(exception)
.hasMessage("invalid user")
.hasViolationOn("name")
.hasViolationOn("age");
assertThatConstraintViolationException(exception)
.extractingConstraintViolations()
.singleElement()
.asInstanceOf(constraintViolation())
.hasMessageTemplate("{jakarta.validation.constraints.NotBlank.message}");The violations are a CollectionAssert<ConstraintViolation<?>> rather than a violation-set assertion because one
exception may carry violations of different root bean types, and the violation-set assertion fixes its root bean
type T. To continue with a typed violation assertion, use asInstanceOf(constraintViolation()) as above.
hasViolationOn compares the path's string form, so a method parameter is written as the provider renders it, for
example "greet.arg0". On failure it lists the paths the exception does have, sorted, or (none) when
getConstraintViolations() is null.
An exception reached as a cause is narrowed with the factory:
assertThat(thrown)
.cause()
.asInstanceOf(CONSTRAINT_VIOLATION_EXCEPTION)
.hasViolationOn("name");See InstanceOf Factories.
assertj-validation · Apache License 2.0 · io.github.jinahya:assertj-validation · Jakarta Validation 3.0 / 3.1 · AssertJ 3.27+ · Java 17+
Running validation
Inspecting results
Reference
External