Add support for strict JSON comparison in WebTestClient
Prior to this commit, WebTestClient only supported "lenient" comparison of the expected JSON body. This commit introduces an overloaded variant of `json()` in the BodyContentSpec that accepts an additional boolean flag to specify whether a "strict" comparison should be performed. This new feature is analogous to the existing support in MockMvc. Closes gh-27993
This commit is contained in:
parent
a13ad3e969
commit
920be8e1b2
|
|
@ -659,10 +659,10 @@ class DefaultWebTestClient implements WebTestClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BodyContentSpec json(String json) {
|
public BodyContentSpec json(String json, boolean strict) {
|
||||||
this.result.assertWithDiagnostics(() -> {
|
this.result.assertWithDiagnostics(() -> {
|
||||||
try {
|
try {
|
||||||
new JsonExpectationsHelper().assertJsonEqual(json, getBodyAsString());
|
new JsonExpectationsHelper().assertJsonEqual(json, getBodyAsString(), strict);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new AssertionError("JSON parsing error", ex);
|
throw new AssertionError("JSON parsing error", ex);
|
||||||
|
|
|
||||||
|
|
@ -979,7 +979,24 @@ public interface WebTestClient {
|
||||||
* on to be on the classpath.
|
* on to be on the classpath.
|
||||||
* @param expectedJson the expected JSON content.
|
* @param expectedJson the expected JSON content.
|
||||||
*/
|
*/
|
||||||
BodyContentSpec json(String expectedJson);
|
default BodyContentSpec json(String expectedJson) {
|
||||||
|
return json(expectedJson, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the expected and actual response content as JSON and perform a
|
||||||
|
* comparison in two modes, depending on {@code strict} parameter value, verifying the same attribute-value pairs.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code true}: strict checking.
|
||||||
|
* <li>{@code false}: lenient checking.
|
||||||
|
* </ul>
|
||||||
|
* <p>Use of this option requires the
|
||||||
|
* <a href="https://jsonassert.skyscreamer.org/">JSONassert</a> library
|
||||||
|
* on to be on the classpath.
|
||||||
|
* @param expectedJson the expected JSON content.
|
||||||
|
* @param strict enables strict checking
|
||||||
|
*/
|
||||||
|
BodyContentSpec json(String expectedJson, boolean strict);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse expected and actual response content as XML and assert that
|
* Parse expected and actual response content as XML and assert that
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,10 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Samples of tests using {@link WebTestClient} with serialized JSON content.
|
* Samples of tests using {@link WebTestClient} with serialized JSON content.
|
||||||
*
|
*
|
||||||
|
|
@ -49,13 +49,32 @@ public class JsonContentTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jsonContent() {
|
public void jsonContent() {
|
||||||
this.client.get().uri("/persons")
|
this.client.get().uri("/persons/extended")
|
||||||
.accept(MediaType.APPLICATION_JSON)
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
.exchange()
|
.exchange()
|
||||||
.expectStatus().isOk()
|
.expectStatus().isOk()
|
||||||
.expectBody().json("[{\"name\":\"Jane\"},{\"name\":\"Jason\"},{\"name\":\"John\"}]");
|
.expectBody().json("[{\"name\":\"Jane\"},{\"name\":\"Jason\"},{\"name\":\"John\"}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void jsonContentStrictFail() {
|
||||||
|
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> this.client.get().uri("/persons/extended")
|
||||||
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk()
|
||||||
|
.expectBody().json("[{\"name\":\"Jane\"},{\"name\":\"Jason\"},{\"name\":\"John\"}]", true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void jsonContentStrict() {
|
||||||
|
this.client.get().uri("/persons/extended")
|
||||||
|
.accept(MediaType.APPLICATION_JSON)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk()
|
||||||
|
.expectBody().json("[{\"name\":\"Jane\",\"surname\":\"Williams\"},{\"name\":\"Jason\",\"surname\":\"Johnson\"},{\"name\":\"John\",\"surname\":\"Smith\"}]", true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jsonPathIsEqualTo() {
|
public void jsonPathIsEqualTo() {
|
||||||
this.client.get().uri("/persons")
|
this.client.get().uri("/persons")
|
||||||
|
|
@ -98,6 +117,11 @@ public class JsonContentTests {
|
||||||
return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John"));
|
return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/extended")
|
||||||
|
Flux<ExtendedPerson> getExtendedPersons() {
|
||||||
|
return Flux.just(new ExtendedPerson("Jane", "Williams"), new ExtendedPerson("Jason", "Johnson"), new ExtendedPerson("John", "Smith"));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{name}")
|
@GetMapping("/{name}")
|
||||||
Person getPerson(@PathVariable String name) {
|
Person getPerson(@PathVariable String name) {
|
||||||
return new Person(name);
|
return new Person(name);
|
||||||
|
|
@ -109,4 +133,22 @@ public class JsonContentTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ExtendedPerson {
|
||||||
|
private String name;
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
public ExtendedPerson(String name, String surname) {
|
||||||
|
this.name = name;
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
return surname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue