Skip to content

Commit

Permalink
Polish AssertJ support for MockMvc
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrannen committed Mar 15, 2024
1 parent 4a74e1f commit cf31d08
Show file tree
Hide file tree
Showing 31 changed files with 275 additions and 257 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@
*/
public class MediaTypeAssert extends AbstractObjectAssert<MediaTypeAssert, MediaType> {

public MediaTypeAssert(@Nullable String actual) {
this(StringUtils.hasText(actual) ? MediaType.parseMediaType(actual) : null);
}

public MediaTypeAssert(@Nullable MediaType mediaType) {
super(mediaType, MediaTypeAssert.class);
as("Media type");
}

public MediaTypeAssert(@Nullable String actual) {
this(StringUtils.hasText(actual) ? MediaType.parseMediaType(actual) : null);
}

/**
* Verify that the actual media type is equal to the given string
Expand All @@ -57,7 +58,8 @@ public MediaTypeAssert isEqualTo(String expected) {
/**
* Verify that the actual media type is
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
* given one. Example: <pre><code class='java'>
* given one.
* <p>Example: <pre><code class='java'>
* // Check that actual is compatible with "application/json"
* assertThat(mediaType).isCompatibleWith(MediaType.APPLICATION_JSON);
* </code></pre>
Expand All @@ -77,7 +79,8 @@ public MediaTypeAssert isCompatibleWith(MediaType mediaType) {
/**
* Verify that the actual media type is
* {@linkplain MediaType#isCompatibleWith(MediaType) compatible} with the
* given one. Example: <pre><code class='java'>
* given one.
* <p>Example: <pre><code class='java'>
* // Check that actual is compatible with "text/plain"
* assertThat(mediaType).isCompatibleWith("text/plain");
* </code></pre>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package org.springframework.test.json;

import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
Expand All @@ -43,8 +42,9 @@

/**
* Base AssertJ {@link org.assertj.core.api.Assert assertions} that can be
* applied to a JSON value. In JSON, values must be one of the following data
* types:
* applied to a JSON value.
*
* <p>In JSON, values must be one of the following data types:
* <ul>
* <li>a {@linkplain #asString() string}</li>
* <li>a {@linkplain #asNumber() number}</li>
Expand All @@ -53,7 +53,7 @@
* <li>an {@linkplain #asMap() object} (JSON object)</li>
* <li>{@linkplain #isNull() null}</li>
* </ul>
* This base class offers direct access for each of those types as well as a
* This base class offers direct access for each of those types as well as
* conversion methods based on an optional {@link GenericHttpMessageConverter}.
*
* @author Stephane Nicoll
Expand All @@ -71,12 +71,14 @@ public abstract class AbstractJsonValueAssert<SELF extends AbstractJsonValueAsse

protected AbstractJsonValueAssert(@Nullable Object actual, Class<?> selfType,
@Nullable GenericHttpMessageConverter<Object> httpMessageConverter) {

super(actual, selfType);
this.httpMessageConverter = httpMessageConverter;
}


/**
* Verify that the actual value is a non-{@code null} {@link String}
* Verify that the actual value is a non-{@code null} {@link String},
* and return a new {@linkplain AbstractStringAssert assertion} object that
* provides dedicated {@code String} assertions for it.
*/
Expand All @@ -87,15 +89,15 @@ public AbstractStringAssert<?> asString() {

/**
* Verify that the actual value is a non-{@code null} {@link Number},
* usually an {@link Integer} or {@link Double} and return a new
* usually an {@link Integer} or {@link Double}, and return a new
* {@linkplain AbstractObjectAssert assertion} object for it.
*/
public AbstractObjectAssert<?, Number> asNumber() {
return Assertions.assertThat(castTo(Number.class, "a number"));
}

/**
* Verify that the actual value is a non-{@code null} {@link Boolean}
* Verify that the actual value is a non-{@code null} {@link Boolean},
* and return a new {@linkplain AbstractBooleanAssert assertion} object
* that provides dedicated {@code Boolean} assertions for it.
*/
Expand All @@ -104,9 +106,9 @@ public AbstractBooleanAssert<?> asBoolean() {
}

/**
* Verify that the actual value is a non-{@code null} {@link Array}
* and return a new {@linkplain ObjectArrayAssert assertion} object
* that provides dedicated {@code Array} assertions for it.
* Verify that the actual value is a non-{@code null} array, and return a
* new {@linkplain ObjectArrayAssert assertion} object that provides dedicated
* array assertions for it.
*/
public ObjectArrayAssert<Object> asArray() {
List<?> list = castTo(List.class, "an array");
Expand All @@ -115,11 +117,12 @@ public ObjectArrayAssert<Object> asArray() {
}

/**
* Verify that the actual value is a non-{@code null} JSON object and
* Verify that the actual value is a non-{@code null} JSON object, and
* return a new {@linkplain AbstractMapAssert assertion} object that
* provides dedicated assertions on individual elements of the
* object. The returned map assertion object uses the attribute name as the
* key, and the value can itself be any of the valid JSON values.
* object.
* <p>The returned map assertion object uses attribute names as the keys,
* and the values can be any of the valid JSON values.
*/
@SuppressWarnings("unchecked")
public AbstractMapAssert<?, Map<String, Object>, String, Object> asMap() {
Expand All @@ -138,7 +141,7 @@ private <T> T castTo(Class<T> expectedType, String description) {

/**
* Verify that the actual value can be converted to an instance of the
* given {@code target} and produce a new {@linkplain AbstractObjectAssert
* given {@code target}, and produce a new {@linkplain AbstractObjectAssert
* assertion} object narrowed to that type.
* @param target the {@linkplain Class type} to convert the actual value to
*/
Expand All @@ -150,7 +153,7 @@ public <T> AbstractObjectAssert<?, T> convertTo(Class<T> target) {

/**
* Verify that the actual value can be converted to an instance of the
* given {@code target} and produce a new {@linkplain AbstractObjectAssert
* given {@code target}, and produce a new {@linkplain AbstractObjectAssert
* assertion} object narrowed to that type.
* @param target the {@linkplain ParameterizedTypeReference parameterized
* type} to convert the actual value to
Expand All @@ -162,9 +165,10 @@ public <T> AbstractObjectAssert<?, T> convertTo(ParameterizedTypeReference<T> ta
}

/**
* Verify that the actual value is empty, that is a {@code null} scalar
* value or an empty list or map. Can also be used when the path is using a
* filter operator to validate that it dit not match.
* Verify that the actual value is empty: either a {@code null} scalar value
* or an empty list or map.
* <p>Can also be used when the path uses a filter operator to validate that
* it did not match.
*/
public SELF isEmpty() {
if (!ObjectUtils.isEmpty(this.actual)) {
Expand All @@ -174,10 +178,10 @@ public SELF isEmpty() {
}

/**
* Verify that the actual value is not empty, that is a non-{@code null}
* scalar value or a non-empty list or map. Can also be used when the path is
* using a filter operator to validate that it dit match at least one
* element.
* Verify that the actual value is not empty: either a non-{@code null}
* scalar value or a non-empty list or map.
* <p>Can also be used when the path uses a filter operator to validate that
* it did match at least one element.
*/
public SELF isNotEmpty() {
if (ObjectUtils.isEmpty(this.actual)) {
Expand Down Expand Up @@ -225,6 +229,7 @@ private String actualToString() {
return ObjectUtils.nullSafeToString(StringUtils.quoteIfString(this.actual));
}


private static final class ValueProcessingFailed extends BasicErrorMessageFactory {

private ValueProcessingFailed(String prefix, String actualToString, String errorMessage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@
import org.springframework.util.Assert;

/**
* JSON content usually created from a JSON tester. Generally used only to
* {@link AssertProvider provide} {@link JsonContentAssert} to AssertJ
* {@code assertThat} calls.
* JSON content which is generally used to {@link AssertProvider provide}
* {@link JsonContentAssert} to AssertJ {@code assertThat} calls.
*
* @author Phillip Webb
* @author Diego Berrueta
Expand All @@ -37,8 +36,9 @@ public final class JsonContent implements AssertProvider<JsonContentAssert> {
@Nullable
private final Class<?> resourceLoadClass;


/**
* Create a new {@link JsonContent} instance.
* Create a new {@code JsonContent} instance.
* @param json the actual JSON content
* @param resourceLoadClass the source class used to load resources
*/
Expand All @@ -48,6 +48,7 @@ public final class JsonContent implements AssertProvider<JsonContentAssert> {
this.resourceLoadClass = resourceLoadClass;
}


/**
* Use AssertJ's {@link org.assertj.core.api.Assertions#assertThat assertThat}
* instead.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

/**
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied
* to a {@link CharSequence} representation of a json document, mostly to
* compare the json document against a target, using {@linkplain JSONCompare
* to a {@link CharSequence} representation of a JSON document, mostly to
* compare the JSON document against a target, using {@linkplain JSONCompare
* JSON Assert}.
*
* @author Phillip Webb
Expand All @@ -57,7 +57,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
* relative to the given {@code resourceLoadClass}, using the given
* {@code charset}.
* @param json the actual JSON content
* @param resourceLoadClass the source class used to load resources
* @param resourceLoadClass the class used to load resources
* @param charset the charset of the JSON resources
*/
public JsonContentAssert(@Nullable CharSequence json, @Nullable Class<?> resourceLoadClass,
Expand All @@ -71,7 +71,7 @@ public JsonContentAssert(@Nullable CharSequence json, @Nullable Class<?> resourc
* Create a new {@link JsonContentAssert} instance that will load resources
* relative to the given {@code resourceLoadClass}, using {@code UTF-8}.
* @param json the actual JSON content
* @param resourceLoadClass the source class used to load resources
* @param resourceLoadClass the class used to load resources
*/
public JsonContentAssert(@Nullable CharSequence json, @Nullable Class<?> resourceLoadClass) {
this(json, resourceLoadClass, null);
Expand Down Expand Up @@ -343,7 +343,6 @@ private JSONCompareResult compare(@Nullable CharSequence actualJson, @Nullable C

private JSONCompareResult compareForNull(@Nullable CharSequence expectedJson) {
JSONCompareResult result = new JSONCompareResult();
result.passed();
if (expectedJson != null) {
result.fail("Expected null JSON");
}
Expand All @@ -352,14 +351,14 @@ private JSONCompareResult compareForNull(@Nullable CharSequence expectedJson) {

private JsonContentAssert assertNotFailed(JSONCompareResult result) {
if (result.failed()) {
failWithMessage("JSON Comparison failure: %s", result.getMessage());
failWithMessage("JSON comparison failure: %s", result.getMessage());
}
return this;
}

private JsonContentAssert assertNotPassed(JSONCompareResult result) {
if (result.passed()) {
failWithMessage("JSON Comparison failure: %s", result.getMessage());
failWithMessage("JSON comparison failure: %s", result.getMessage());
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,23 @@ class JsonLoader {

private final Charset charset;


JsonLoader(@Nullable Class<?> resourceLoadClass, @Nullable Charset charset) {
this.resourceLoadClass = resourceLoadClass;
this.charset = (charset != null ? charset : StandardCharsets.UTF_8);
}


@Nullable
String getJson(@Nullable CharSequence source) {
if (source == null) {
return null;
}
if (source.toString().endsWith(".json")) {
return getJson(new ClassPathResource(source.toString(), this.resourceLoadClass));
String string = source.toString();
if (string.endsWith(".json")) {
return getJson(new ClassPathResource(string, this.resourceLoadClass));
}
return source.toString();
return string;
}

String getJson(Resource source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

/**
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied
* to a {@link CharSequence} representation of a json document using
* to a {@link CharSequence} representation of a JSON document using
* {@linkplain JsonPath JSON path}.
*
* @author Stephane Nicoll
Expand All @@ -41,17 +41,21 @@ public class JsonPathAssert extends AbstractAssert<JsonPathAssert, CharSequence>

private static final Failures failures = Failures.instance();


@Nullable
private final GenericHttpMessageConverter<Object> jsonMessageConverter;


public JsonPathAssert(CharSequence json,
@Nullable GenericHttpMessageConverter<Object> jsonMessageConverter) {

super(json, JsonPathAssert.class);
this.jsonMessageConverter = jsonMessageConverter;
}


/**
* Verify that the given JSON {@code path} is present and extract the JSON
* Verify that the given JSON {@code path} is present, and extract the JSON
* value for further {@linkplain JsonPathValueAssert assertions}.
* @param path the {@link JsonPath} expression
* @see #hasPathSatisfying(String, Consumer)
Expand Down Expand Up @@ -158,8 +162,9 @@ private JsonPathNotFound(String actual, String path) {
static final class JsonPathNotExpected extends BasicErrorMessageFactory {

private JsonPathNotExpected(String actual, String path) {
super("%nExpecting:%n %s%nTo not match JSON path:%n %s%n", actual, path);
super("%nExpecting:%n %s%nNot to match JSON path:%n %s%n", actual, path);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
* @author Stephane Nicoll
* @since 6.2
*/
public class JsonPathValueAssert
extends AbstractJsonValueAssert<JsonPathValueAssert> {
public class JsonPathValueAssert extends AbstractJsonValueAssert<JsonPathValueAssert> {

private final String expression;


JsonPathValueAssert(@Nullable Object actual, String expression,
@Nullable GenericHttpMessageConverter<Object> httpMessageConverter) {

super(actual, JsonPathValueAssert.class, httpMessageConverter);
this.expression = expression;
}
Expand All @@ -45,4 +45,5 @@ public class JsonPathValueAssert
protected String getExpectedErrorMessagePrefix() {
return "Expected value at JSON path \"%s\":".formatted(this.expression);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ public abstract class AbstractBindingResultAssert<SELF extends AbstractBindingRe

private final String name;


protected AbstractBindingResultAssert(String name, BindingResult bindingResult, Class<?> selfType) {
super(bindingResult, selfType);
this.name = name;
as("Binding result for attribute '%s", this.name);
}

/**
* Verify that the total number of errors is equal to the given one.
* Verify that the total number of errors is equal to the expected value.
* @param expected the expected number of errors
*/
public SELF hasErrorsCount(int expected) {
Expand All @@ -73,7 +74,7 @@ public SELF hasFieldErrors(String... fieldNames) {
/**
* Verify that the actual binding result contains <em>only</em> fields in
* error with the given {@code fieldNames}, and nothing else.
* @param fieldNames the exhaustive list of field name that should be in error
* @param fieldNames the exhaustive list of field names that should be in error
*/
public SELF hasOnlyFieldErrors(String... fieldNames) {
assertThat(fieldErrorNames()).containsOnly(fieldNames);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public UriAssert isEqualToTemplate(String uriTemplate, Object... uriVars) {
* </code></pre>
* @param uriPattern the pattern that is expected to match
*/
public UriAssert matchPattern(String uriPattern) {
public UriAssert matchesPattern(String uriPattern) {
Assertions.assertThat(pathMatcher.isPattern(uriPattern))
.withFailMessage("'%s' is not an Ant-style path pattern", uriPattern).isTrue();
Assertions.assertThat(pathMatcher.match(uriPattern, this.actual))
Expand Down
Loading

0 comments on commit cf31d08

Please sign in to comment.