From aa4b226a2252cfde817a22ea79d533efde2de882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Tue, 4 Jun 2024 17:01:59 +0200 Subject: [PATCH] Add support for converting json values using AssertFactory This commit benefits from a feature introduced in AssertJ 3.26.0, see https://github.com/assertj/assertj/pull/3377. This allows to use any AssertFactory and convert the actual value to the type the factory manages. Previously, we were using ParameterizedTypeReference to express the type with its generic signature but the returned assert object would not be narrowed to the converted type. Thanks to this change, we can request to convert the actual value to `InstanceOfAssertFactories.list(Member.class)` and get a `ListAssert` of `Member` as a result, rather than an `ObjectAssert` of `List`. Thanks very much to @scordio for his efforts. Closes gh-32953 --- .../test/json/AbstractJsonValueAssert.java | 27 ++++++++++++------- .../json/AbstractJsonContentAssertTests.java | 6 ++--- .../test/json/JsonPathValueAssertTests.java | 6 ++--- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/json/AbstractJsonValueAssert.java b/spring-test/src/main/java/org/springframework/test/json/AbstractJsonValueAssert.java index d066a12cd2..e36cbd2755 100644 --- a/spring-test/src/main/java/org/springframework/test/json/AbstractJsonValueAssert.java +++ b/spring-test/src/main/java/org/springframework/test/json/AbstractJsonValueAssert.java @@ -20,16 +20,18 @@ import java.lang.reflect.Type; import java.util.List; import java.util.Map; +import org.assertj.core.api.AbstractAssert; import org.assertj.core.api.AbstractBooleanAssert; import org.assertj.core.api.AbstractMapAssert; import org.assertj.core.api.AbstractObjectAssert; import org.assertj.core.api.AbstractStringAssert; +import org.assertj.core.api.AssertFactory; import org.assertj.core.api.Assertions; +import org.assertj.core.api.InstanceOfAssertFactories; import org.assertj.core.api.ObjectArrayAssert; import org.assertj.core.error.BasicErrorMessageFactory; import org.assertj.core.internal.Failures; -import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ResolvableType; import org.springframework.http.HttpInputMessage; import org.springframework.http.MediaType; @@ -152,16 +154,23 @@ public abstract class AbstractJsonValueAssert{@link InstanceOfAssertFactories} provides static factories for all the + * types supported by {@link Assertions#assertThat}. Additional factories can + * be created by implementing {@link AssertFactory}. + *

Example:


+	 * // Check that the json value is an array of 3 users
+	 * assertThat(jsonValue).convertTo(InstanceOfAssertFactories.list(User.class))
+	 *         hasSize(3); // ListAssert of User
+	 * 
+ * @param assertFactory the {@link AssertFactory} to use to produce a narrowed + * Assert for the type that it defines. */ - public AbstractObjectAssert convertTo(ParameterizedTypeReference target) { + public > ASSERT convertTo(AssertFactory assertFactory) { isNotNull(); - T value = convertToTargetType(target.getType()); - return Assertions.assertThat(value); + return assertFactory.createAssert(this::convertToTargetType); } /** diff --git a/spring-test/src/test/java/org/springframework/test/json/AbstractJsonContentAssertTests.java b/spring-test/src/test/java/org/springframework/test/json/AbstractJsonContentAssertTests.java index 0c350c4135..80ebee1c56 100644 --- a/spring-test/src/test/java/org/springframework/test/json/AbstractJsonContentAssertTests.java +++ b/spring-test/src/test/java/org/springframework/test/json/AbstractJsonContentAssertTests.java @@ -28,6 +28,7 @@ import java.util.stream.Stream; import com.fasterxml.jackson.databind.ObjectMapper; import org.assertj.core.api.AssertProvider; +import org.assertj.core.api.InstanceOfAssertFactories; import org.json.JSONException; import org.json.JSONObject; import org.junit.jupiter.api.Nested; @@ -42,7 +43,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.skyscreamer.jsonassert.JSONCompareResult; import org.skyscreamer.jsonassert.comparator.JSONComparator; -import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; @@ -286,8 +286,8 @@ class AbstractJsonContentAssertTests { void convertArrayToParameterizedType() { assertThat(forJson(SIMPSONS, jsonHttpMessageConverter)) .extractingPath("$.familyMembers") - .convertTo(new ParameterizedTypeReference>() {}) - .satisfies(family -> assertThat(family).hasSize(5).element(0).isEqualTo(new Member("Homer"))); + .convertTo(InstanceOfAssertFactories.list(Member.class)) + .hasSize(5).element(0).isEqualTo(new Member("Homer")); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/json/JsonPathValueAssertTests.java b/spring-test/src/test/java/org/springframework/test/json/JsonPathValueAssertTests.java index 4ed5f604ca..54d4ac26f9 100644 --- a/spring-test/src/test/java/org/springframework/test/json/JsonPathValueAssertTests.java +++ b/spring-test/src/test/java/org/springframework/test/json/JsonPathValueAssertTests.java @@ -28,7 +28,6 @@ import org.assertj.core.data.Offset; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -231,9 +230,8 @@ class JsonPathValueAssertTests { Map user2 = Map.of("id", 5678, "name", "Sarah", "active", false); Map user3 = Map.of("id", 9012, "name", "Sophia", "active", true); assertThat(forValue(List.of(user1, user2, user3))) - .convertTo(new ParameterizedTypeReference>() {}) - .satisfies(users -> assertThat(users).hasSize(3).extracting("name") - .containsExactly("John", "Sarah", "Sophia")); + .convertTo(InstanceOfAssertFactories.list(User.class)) + .hasSize(3).extracting("name").containsExactly("John", "Sarah", "Sophia"); } @Test