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<User>`. Thanks very much to @scordio for his efforts. Closes gh-32953
This commit is contained in:
@@ -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<SELF extends AbstractJsonValueAsse
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the actual value can be converted to an instance of the
|
||||
* given {@code target}, and produce a new {@linkplain AbstractObjectAssert
|
||||
* assertion} object narrowed to that type.
|
||||
* @param target the {@linkplain ParameterizedTypeReference parameterized
|
||||
* type} to convert the actual value to
|
||||
* Verify that the actual value can be converted to an instance of the type
|
||||
* defined by the given {@link AssertFactory} and return a new Assert narrowed
|
||||
* to that type.
|
||||
* <p>{@link InstanceOfAssertFactories} provides static factories for all the
|
||||
* types supported by {@link Assertions#assertThat}. Additional factories can
|
||||
* be created by implementing {@link AssertFactory}.
|
||||
* <p>Example: <pre><code class="java">
|
||||
* // Check that the json value is an array of 3 users
|
||||
* assertThat(jsonValue).convertTo(InstanceOfAssertFactories.list(User.class))
|
||||
* hasSize(3); // ListAssert of User
|
||||
* </code></pre>
|
||||
* @param assertFactory the {@link AssertFactory} to use to produce a narrowed
|
||||
* Assert for the type that it defines.
|
||||
*/
|
||||
public <T> AbstractObjectAssert<?, T> convertTo(ParameterizedTypeReference<T> target) {
|
||||
public <ASSERT extends AbstractAssert<?, ?>> ASSERT convertTo(AssertFactory<?, ASSERT> assertFactory) {
|
||||
isNotNull();
|
||||
T value = convertToTargetType(target.getType());
|
||||
return Assertions.assertThat(value);
|
||||
return assertFactory.createAssert(this::convertToTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<List<Member>>() {})
|
||||
.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
|
||||
|
||||
@@ -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<List<User>>() {})
|
||||
.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
|
||||
|
||||
Reference in New Issue
Block a user