Skip to content

Commit 24cc776

Browse files
committed
Merge JSON assertions in a single Assert type
This commit merges the JSONCompare and JsonPath support in a single assert object. The rationale for the previous situation was that JsonPath is optional but merging the assertions methods do not make it mandatory as the usage if JsonPath is triggered only if it is actually used. See gh-32712
1 parent 645556a commit 24cc776

File tree

9 files changed

+1322
-1325
lines changed

9 files changed

+1322
-1325
lines changed

spring-test/src/main/java/org/springframework/test/json/AbstractJsonContentAssert.java

+501
Large diffs are not rendered by default.

spring-test/src/main/java/org/springframework/test/json/JsonContent.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public final class JsonContent implements AssertProvider<JsonContentAssert> {
5555
*/
5656
@Override
5757
public JsonContentAssert assertThat() {
58-
return new JsonContentAssert(this.json, this.resourceLoadClass, null);
58+
return new JsonContentAssert(this.json, null, this.resourceLoadClass, null);
5959
}
6060

6161
/**

spring-test/src/main/java/org/springframework/test/json/JsonContentAssert.java

+17-332
Original file line numberDiff line numberDiff line change
@@ -16,351 +16,36 @@
1616

1717
package org.springframework.test.json;
1818

19-
import java.io.File;
20-
import java.io.InputStream;
2119
import java.nio.charset.Charset;
22-
import java.nio.file.Path;
2320

24-
import org.assertj.core.api.AbstractAssert;
25-
import org.skyscreamer.jsonassert.JSONCompare;
26-
import org.skyscreamer.jsonassert.JSONCompareMode;
27-
import org.skyscreamer.jsonassert.JSONCompareResult;
28-
import org.skyscreamer.jsonassert.comparator.JSONComparator;
29-
30-
import org.springframework.core.io.ByteArrayResource;
31-
import org.springframework.core.io.ClassPathResource;
32-
import org.springframework.core.io.FileSystemResource;
33-
import org.springframework.core.io.InputStreamResource;
34-
import org.springframework.core.io.Resource;
21+
import org.springframework.http.converter.GenericHttpMessageConverter;
3522
import org.springframework.lang.Nullable;
36-
import org.springframework.util.function.ThrowingBiFunction;
3723

3824
/**
39-
* AssertJ {@link org.assertj.core.api.Assert assertions} that can be applied
40-
* to a {@link CharSequence} representation of a JSON document, mostly to
41-
* compare the JSON document against a target, using {@linkplain JSONCompare
42-
* JSON Assert}.
25+
* Default {@link AbstractJsonContentAssert} implementation.
4326
*
44-
* @author Phillip Webb
45-
* @author Andy Wilkinson
46-
* @author Diego Berrueta
47-
* @author Camille Vienot
4827
* @author Stephane Nicoll
4928
* @since 6.2
5029
*/
51-
public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSequence> {
52-
53-
private final JsonLoader loader;
54-
55-
/**
56-
* Create a new {@link JsonContentAssert} instance that will load resources
57-
* relative to the given {@code resourceLoadClass}, using the given
58-
* {@code charset}.
59-
* @param json the actual JSON content
30+
public class JsonContentAssert extends AbstractJsonContentAssert<JsonContentAssert> {
31+
32+
/**
33+
* Create an assert for the given JSON document.
34+
* <p>Path can be converted to a value object using the given
35+
* {@linkplain GenericHttpMessageConverter json message converter}.
36+
* <p>Resources to match can be loaded relative to the given
37+
* {@code resourceLoadClass}. If not specified, resources must always be
38+
* absolute. A specific {@link Charset} can be provided if {@code UTF-8} is
39+
* not suitable.
40+
* @param json the JSON document to assert
41+
* @param jsonMessageConverter the converter to use
6042
* @param resourceLoadClass the class used to load resources
6143
* @param charset the charset of the JSON resources
6244
*/
63-
public JsonContentAssert(@Nullable CharSequence json, @Nullable Class<?> resourceLoadClass,
64-
@Nullable Charset charset) {
65-
66-
super(json, JsonContentAssert.class);
67-
this.loader = new JsonLoader(resourceLoadClass, charset);
68-
}
69-
70-
/**
71-
* Create a new {@link JsonContentAssert} instance that will load resources
72-
* relative to the given {@code resourceLoadClass}, using {@code UTF-8}.
73-
* @param json the actual JSON content
74-
* @param resourceLoadClass the class used to load resources
75-
*/
76-
public JsonContentAssert(@Nullable CharSequence json, @Nullable Class<?> resourceLoadClass) {
77-
this(json, resourceLoadClass, null);
78-
}
79-
80-
81-
/**
82-
* Verify that the actual value is equal to the given JSON. The
83-
* {@code expected} value can contain the JSON itself or, if it ends with
84-
* {@code .json}, the name of a resource to be loaded from the classpath.
85-
* @param expected the expected JSON or the name of a resource containing
86-
* the expected JSON
87-
* @param compareMode the compare mode used when checking
88-
*/
89-
public JsonContentAssert isEqualTo(@Nullable CharSequence expected, JSONCompareMode compareMode) {
90-
String expectedJson = this.loader.getJson(expected);
91-
return assertNotFailed(compare(expectedJson, compareMode));
92-
}
93-
94-
/**
95-
* Verify that the actual value is equal to the given JSON {@link Resource}.
96-
* <p>The resource abstraction allows to provide several input types:
97-
* <ul>
98-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
99-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
100-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
101-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
102-
* </ul>
103-
* @param expected a resource containing the expected JSON
104-
* @param compareMode the compare mode used when checking
105-
*/
106-
public JsonContentAssert isEqualTo(Resource expected, JSONCompareMode compareMode) {
107-
String expectedJson = this.loader.getJson(expected);
108-
return assertNotFailed(compare(expectedJson, compareMode));
109-
}
110-
111-
/**
112-
* Verify that the actual value is equal to the given JSON. The
113-
* {@code expected} value can contain the JSON itself or, if it ends with
114-
* {@code .json}, the name of a resource to be loaded from the classpath.
115-
* @param expected the expected JSON or the name of a resource containing
116-
* the expected JSON
117-
* @param comparator the comparator used when checking
118-
*/
119-
public JsonContentAssert isEqualTo(@Nullable CharSequence expected, JSONComparator comparator) {
120-
String expectedJson = this.loader.getJson(expected);
121-
return assertNotFailed(compare(expectedJson, comparator));
122-
}
123-
124-
/**
125-
* Verify that the actual value is equal to the given JSON {@link Resource}.
126-
* <p>The resource abstraction allows to provide several input types:
127-
* <ul>
128-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
129-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
130-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
131-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
132-
* </ul>
133-
* @param expected a resource containing the expected JSON
134-
* @param comparator the comparator used when checking
135-
*/
136-
public JsonContentAssert isEqualTo(Resource expected, JSONComparator comparator) {
137-
String expectedJson = this.loader.getJson(expected);
138-
return assertNotFailed(compare(expectedJson, comparator));
139-
}
140-
141-
/**
142-
* Verify that the actual value is {@link JSONCompareMode#LENIENT leniently}
143-
* equal to the given JSON. The {@code expected} value can contain the JSON
144-
* itself or, if it ends with {@code .json}, the name of a resource to be
145-
* loaded from the classpath.
146-
* @param expected the expected JSON or the name of a resource containing
147-
* the expected JSON
148-
*/
149-
public JsonContentAssert isLenientlyEqualTo(@Nullable CharSequence expected) {
150-
return isEqualTo(expected, JSONCompareMode.LENIENT);
151-
}
152-
153-
/**
154-
* Verify that the actual value is {@link JSONCompareMode#LENIENT leniently}
155-
* equal to the given JSON {@link Resource}.
156-
* <p>The resource abstraction allows to provide several input types:
157-
* <ul>
158-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
159-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
160-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
161-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
162-
* </ul>
163-
* @param expected a resource containing the expected JSON
164-
*/
165-
public JsonContentAssert isLenientlyEqualTo(Resource expected) {
166-
return isEqualTo(expected, JSONCompareMode.LENIENT);
167-
}
168-
169-
/**
170-
* Verify that the actual value is {@link JSONCompareMode#STRICT strictly}
171-
* equal to the given JSON. The {@code expected} value can contain the JSON
172-
* itself or, if it ends with {@code .json}, the name of a resource to be
173-
* loaded from the classpath.
174-
* @param expected the expected JSON or the name of a resource containing
175-
* the expected JSON
176-
*/
177-
public JsonContentAssert isStrictlyEqualTo(@Nullable CharSequence expected) {
178-
return isEqualTo(expected, JSONCompareMode.STRICT);
179-
}
180-
181-
/**
182-
* Verify that the actual value is {@link JSONCompareMode#STRICT strictly}
183-
* equal to the given JSON {@link Resource}.
184-
* <p>The resource abstraction allows to provide several input types:
185-
* <ul>
186-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
187-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
188-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
189-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
190-
* </ul>
191-
* @param expected a resource containing the expected JSON
192-
*/
193-
public JsonContentAssert isStrictlyEqualTo(Resource expected) {
194-
return isEqualTo(expected, JSONCompareMode.STRICT);
195-
}
196-
197-
/**
198-
* Verify that the actual value is not equal to the given JSON. The
199-
* {@code expected} value can contain the JSON itself or, if it ends with
200-
* {@code .json}, the name of a resource to be loaded from the classpath.
201-
* @param expected the expected JSON or the name of a resource containing
202-
* the expected JSON
203-
* @param compareMode the compare mode used when checking
204-
*/
205-
public JsonContentAssert isNotEqualTo(@Nullable CharSequence expected, JSONCompareMode compareMode) {
206-
String expectedJson = this.loader.getJson(expected);
207-
return assertNotPassed(compare(expectedJson, compareMode));
208-
}
209-
210-
/**
211-
* Verify that the actual value is not equal to the given JSON {@link Resource}.
212-
* <p>The resource abstraction allows to provide several input types:
213-
* <ul>
214-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
215-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
216-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
217-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
218-
* </ul>
219-
* @param expected a resource containing the expected JSON
220-
* @param compareMode the compare mode used when checking
221-
*/
222-
public JsonContentAssert isNotEqualTo(Resource expected, JSONCompareMode compareMode) {
223-
String expectedJson = this.loader.getJson(expected);
224-
return assertNotPassed(compare(expectedJson, compareMode));
225-
}
226-
227-
/**
228-
* Verify that the actual value is not equal to the given JSON. The
229-
* {@code expected} value can contain the JSON itself or, if it ends with
230-
* {@code .json}, the name of a resource to be loaded from the classpath.
231-
* @param expected the expected JSON or the name of a resource containing
232-
* the expected JSON
233-
* @param comparator the comparator used when checking
234-
*/
235-
public JsonContentAssert isNotEqualTo(@Nullable CharSequence expected, JSONComparator comparator) {
236-
String expectedJson = this.loader.getJson(expected);
237-
return assertNotPassed(compare(expectedJson, comparator));
238-
}
239-
240-
/**
241-
* Verify that the actual value is not equal to the given JSON {@link Resource}.
242-
* <p>The resource abstraction allows to provide several input types:
243-
* <ul>
244-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
245-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
246-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
247-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
248-
* </ul>
249-
* @param expected a resource containing the expected JSON
250-
* @param comparator the comparator used when checking
251-
*/
252-
public JsonContentAssert isNotEqualTo(Resource expected, JSONComparator comparator) {
253-
String expectedJson = this.loader.getJson(expected);
254-
return assertNotPassed(compare(expectedJson, comparator));
255-
}
256-
257-
/**
258-
* Verify that the actual value is not {@link JSONCompareMode#LENIENT
259-
* leniently} equal to the given JSON. The {@code expected} value can
260-
* contain the JSON itself or, if it ends with {@code .json}, the name of a
261-
* resource to be loaded from the classpath.
262-
* @param expected the expected JSON or the name of a resource containing
263-
* the expected JSON
264-
*/
265-
public JsonContentAssert isNotLenientlyEqualTo(@Nullable CharSequence expected) {
266-
return isNotEqualTo(expected, JSONCompareMode.LENIENT);
267-
}
268-
269-
/**
270-
* Verify that the actual value is not {@link JSONCompareMode#LENIENT
271-
* leniently} equal to the given JSON {@link Resource}.
272-
* <p>The resource abstraction allows to provide several input types:
273-
* <ul>
274-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
275-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
276-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
277-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
278-
* </ul>
279-
* @param expected a resource containing the expected JSON
280-
*/
281-
public JsonContentAssert isNotLenientlyEqualTo(Resource expected) {
282-
return isNotEqualTo(expected, JSONCompareMode.LENIENT);
283-
}
284-
285-
/**
286-
* Verify that the actual value is not {@link JSONCompareMode#STRICT
287-
* strictly} equal to the given JSON. The {@code expected} value can
288-
* contain the JSON itself or, if it ends with {@code .json}, the name of a
289-
* resource to be loaded from the classpath.
290-
* @param expected the expected JSON or the name of a resource containing
291-
* the expected JSON
292-
*/
293-
public JsonContentAssert isNotStrictlyEqualTo(@Nullable CharSequence expected) {
294-
return isNotEqualTo(expected, JSONCompareMode.STRICT);
295-
}
296-
297-
/**
298-
* Verify that the actual value is not {@link JSONCompareMode#STRICT
299-
* strictly} equal to the given JSON {@link Resource}.
300-
* <p>The resource abstraction allows to provide several input types:
301-
* <ul>
302-
* <li>a {@code byte} array, using {@link ByteArrayResource}</li>
303-
* <li>a {@code classpath} resource, using {@link ClassPathResource}</li>
304-
* <li>a {@link File} or {@link Path}, using {@link FileSystemResource}</li>
305-
* <li>an {@link InputStream}, using {@link InputStreamResource}</li>
306-
* </ul>
307-
* @param expected a resource containing the expected JSON
308-
*/
309-
public JsonContentAssert isNotStrictlyEqualTo(Resource expected) {
310-
return isNotEqualTo(expected, JSONCompareMode.STRICT);
311-
}
312-
313-
314-
private JSONCompareResult compare(@Nullable CharSequence expectedJson, JSONCompareMode compareMode) {
315-
return compare(this.actual, expectedJson, (actualJsonString, expectedJsonString) ->
316-
JSONCompare.compareJSON(expectedJsonString, actualJsonString, compareMode));
317-
}
318-
319-
private JSONCompareResult compare(@Nullable CharSequence expectedJson, JSONComparator comparator) {
320-
return compare(this.actual, expectedJson, (actualJsonString, expectedJsonString) ->
321-
JSONCompare.compareJSON(expectedJsonString, actualJsonString, comparator));
322-
}
323-
324-
private JSONCompareResult compare(@Nullable CharSequence actualJson, @Nullable CharSequence expectedJson,
325-
ThrowingBiFunction<String, String, JSONCompareResult> comparator) {
326-
327-
if (actualJson == null) {
328-
return compareForNull(expectedJson);
329-
}
330-
if (expectedJson == null) {
331-
return compareForNull(actualJson.toString());
332-
}
333-
try {
334-
return comparator.applyWithException(actualJson.toString(), expectedJson.toString());
335-
}
336-
catch (Exception ex) {
337-
if (ex instanceof RuntimeException runtimeException) {
338-
throw runtimeException;
339-
}
340-
throw new IllegalStateException(ex);
341-
}
342-
}
343-
344-
private JSONCompareResult compareForNull(@Nullable CharSequence expectedJson) {
345-
JSONCompareResult result = new JSONCompareResult();
346-
if (expectedJson != null) {
347-
result.fail("Expected null JSON");
348-
}
349-
return result;
350-
}
351-
352-
private JsonContentAssert assertNotFailed(JSONCompareResult result) {
353-
if (result.failed()) {
354-
failWithMessage("JSON comparison failure: %s", result.getMessage());
355-
}
356-
return this;
357-
}
45+
public JsonContentAssert(@Nullable String json, @Nullable GenericHttpMessageConverter<Object> jsonMessageConverter,
46+
@Nullable Class<?> resourceLoadClass, @Nullable Charset charset) {
35847

359-
private JsonContentAssert assertNotPassed(JSONCompareResult result) {
360-
if (result.passed()) {
361-
failWithMessage("JSON comparison failure: %s", result.getMessage());
362-
}
363-
return this;
48+
super(json, jsonMessageConverter, resourceLoadClass, charset, JsonContentAssert.class);
36449
}
36550

36651
}

0 commit comments

Comments
 (0)