From 920be8e1b201fa947b07941eeace62ecf0f431a9 Mon Sep 17 00:00:00 2001 From: Gleidson Leopoldo Date: Tue, 1 Feb 2022 09:26:14 +0000 Subject: [PATCH] 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 --- .../reactive/server/DefaultWebTestClient.java | 4 +- .../web/reactive/server/WebTestClient.java | 19 +++++++- .../server/samples/JsonContentTests.java | 46 ++++++++++++++++++- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java index 8628ef2622..3c0a33cb67 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/DefaultWebTestClient.java @@ -659,10 +659,10 @@ class DefaultWebTestClient implements WebTestClient { } @Override - public BodyContentSpec json(String json) { + public BodyContentSpec json(String json, boolean strict) { this.result.assertWithDiagnostics(() -> { try { - new JsonExpectationsHelper().assertJsonEqual(json, getBodyAsString()); + new JsonExpectationsHelper().assertJsonEqual(json, getBodyAsString(), strict); } catch (Exception ex) { throw new AssertionError("JSON parsing error", ex); diff --git a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java index 141428f171..b8115a2e54 100644 --- a/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java +++ b/spring-test/src/main/java/org/springframework/test/web/reactive/server/WebTestClient.java @@ -979,7 +979,24 @@ public interface WebTestClient { * on to be on the classpath. * @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. + * + *

Use of this option requires the + * JSONassert 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 diff --git a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java index 82d271c877..2df1ad44ad 100644 --- a/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/reactive/server/samples/JsonContentTests.java @@ -31,10 +31,10 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.hamcrest.Matchers.containsString; - /** * Samples of tests using {@link WebTestClient} with serialized JSON content. * @@ -49,13 +49,32 @@ public class JsonContentTests { @Test public void jsonContent() { - this.client.get().uri("/persons") + this.client.get().uri("/persons/extended") .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .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 public void jsonPathIsEqualTo() { this.client.get().uri("/persons") @@ -98,6 +117,11 @@ public class JsonContentTests { return Flux.just(new Person("Jane"), new Person("Jason"), new Person("John")); } + @GetMapping("/extended") + Flux getExtendedPersons() { + return Flux.just(new ExtendedPerson("Jane", "Williams"), new ExtendedPerson("Jason", "Johnson"), new ExtendedPerson("John", "Smith")); + } + @GetMapping("/{name}") Person getPerson(@PathVariable String 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; + } + } + }