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 d066a12cd26..e36cbd27554 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 0c350c41357..80ebee1c568 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 4ed5f604cac..54d4ac26f98 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