Skip to content

Commit

Permalink
#859 Support for JsonPath in Spring
Browse files Browse the repository at this point in the history
  • Loading branch information
lukas-krecan committed Nov 28, 2024
1 parent 3ba3d49 commit 6266fbc
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package net.javacrumbs.jsonunit.spring;

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
Expand All @@ -24,18 +26,22 @@
abstract class AbstractSpringMatcher {
private final Path path;
private final Configuration configuration;
private final BiConsumer<Object, InternalMatcher> matcher;
private final Consumer<InternalMatcher> matcher;
private final Function<Object, Object> jsonTransformer;

AbstractSpringMatcher(
@NotNull Path path,
@NotNull Configuration configuration,
@NotNull BiConsumer<Object, InternalMatcher> matcher) {
@NotNull Path path,
@NotNull Configuration configuration,
@NotNull Consumer<InternalMatcher> matcher,
@NotNull Function<Object, Object> jsonTransformer
) {
this.path = path;
this.configuration = configuration;
this.matcher = matcher;
this.jsonTransformer = jsonTransformer;
}

void doMatch(Object actual) {
matcher.accept(actual, new InternalMatcher(actual, path, "", configuration));
matcher.accept(new InternalMatcher(jsonTransformer.apply(actual), path, "", configuration));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

import java.math.BigDecimal;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.ConfigurationWhen;
import net.javacrumbs.jsonunit.core.Option;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
import net.javacrumbs.jsonunit.core.listener.DifferenceListener;
import net.javacrumbs.jsonunit.jsonpath.JsonPathAdapter;
import org.hamcrest.Matcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -35,17 +38,23 @@
abstract class AbstractSpringMatchers<ME, MATCHER> {
final Path path;
final Configuration configuration;
final Function<Object, Object> jsonTransformer;

AbstractSpringMatchers(@NotNull Path path, @NotNull Configuration configuration) {
AbstractSpringMatchers(@NotNull Path path, @NotNull Configuration configuration, Function<Object, Object> jsonTransformer) {
this.path = path;
this.configuration = configuration;
this.jsonTransformer = jsonTransformer;
}

@NotNull
abstract MATCHER matcher(@NotNull BiConsumer<Object, InternalMatcher> matcher);
abstract MATCHER matcher(@NotNull Consumer<InternalMatcher> matcher);

@NotNull
abstract ME matchers(@NotNull Path path, @NotNull Configuration configuration);
abstract ME matchers(@NotNull Path path, @NotNull Configuration configuration, @NotNull Function<Object, Object> jsonTransformer);

protected ME matchers(@NotNull Path path, @NotNull Configuration configuration) {
return matchers(path, configuration, jsonTransformer);
}

/**
* Creates a matcher object that only compares given node.
Expand All @@ -55,14 +64,21 @@ abstract class AbstractSpringMatchers<ME, MATCHER> {
* this.mockMvc.perform(get("/sample").accept(MediaType.APPLICATION_JSON)).andExpect(json().node("root.test[0]").isEqualTo("1"));
* </code>
*
* @param newPath
* @return object comparing only node given by path.
*/
@NotNull
public ME node(String newPath) {
return matchers(path.copy(newPath), configuration);
}

/**
* Uses JsonPath to extract values from the actual value.
*/
@NotNull
public ME inPath(String path) {
return matchers(this.path, configuration, json -> JsonPathAdapter.inPath(json, path));
}

/**
* Sets the placeholder that can be used to ignore values.
* The default value is ${json-unit.ignore}
Expand Down Expand Up @@ -143,7 +159,7 @@ public ME when(
*/
@NotNull
public MATCHER isEqualTo(@Nullable Object expected) {
return matcher((actual, ctx) -> ctx.isEqualTo(expected));
return matcher(ctx -> ctx.isEqualTo(expected));
}

/**
Expand All @@ -152,7 +168,7 @@ public MATCHER isEqualTo(@Nullable Object expected) {
*/
@NotNull
public MATCHER isStringEqualTo(@Nullable final String expected) {
return matcher((actual, ctx) -> ctx.isStringEqualTo(expected));
return matcher(ctx -> ctx.isStringEqualTo(expected));
}

/**
Expand All @@ -161,63 +177,63 @@ public MATCHER isStringEqualTo(@Nullable final String expected) {
*/
@NotNull
public MATCHER isNotEqualTo(@Nullable Object expected) {
return matcher((actual, ctx) -> ctx.isNotEqualTo(expected));
return matcher(ctx -> ctx.isNotEqualTo(expected));
}

/**
* Fails if the node exists.
*/
@NotNull
public MATCHER isAbsent() {
return matcher((actual, ctx) -> ctx.isAbsent());
return matcher(ctx -> ctx.isAbsent());
}

/**
* Fails if the node is missing.
*/
@NotNull
public MATCHER isPresent() {
return matcher((actual, ctx) -> ctx.isPresent());
return matcher(InternalMatcher::isPresent);
}

/**
* Fails if the selected JSON is not an Array or is not present.
*/
@NotNull
public MATCHER isArray() {
return matcher((actual, ctx) -> ctx.isArray());
return matcher(InternalMatcher::isArray);
}

/**
* Fails if the selected JSON is not an Object or is not present.
*/
@NotNull
public MATCHER isObject() {
return matcher((actual, ctx) -> ctx.isObject());
return matcher(InternalMatcher::isObject);
}

/**
* Fails if the selected JSON is not a String or is not present.
*/
@NotNull
public MATCHER isString() {
return matcher((actual, ctx) -> ctx.isString());
return matcher(InternalMatcher::isString);
}

/**
* Fails if selected JSON is not null.
*/
@NotNull
public MATCHER isNull() {
return matcher((actual, ctx) -> ctx.isNull());
return matcher(InternalMatcher::isNull);
}

/**
* Fails if selected JSON is null.
*/
@NotNull
public MATCHER isNotNull() {
return matcher((actual, ctx) -> ctx.isNotNull());
return matcher(InternalMatcher::isNotNull);
}

/**
Expand All @@ -234,7 +250,7 @@ public MATCHER isNotNull() {
*/
@NotNull
public MATCHER matches(@NotNull final Matcher<?> matcher) {
return matcher((actual, ctx) -> ctx.matches(matcher));
return matcher(ctx -> ctx.matches(matcher));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package net.javacrumbs.jsonunit.spring;

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
Expand All @@ -37,36 +39,37 @@
*/
public class JsonUnitRequestMatchers extends AbstractSpringMatchers<JsonUnitRequestMatchers, RequestMatcher> {

private JsonUnitRequestMatchers(Path path, Configuration configuration) {
super(path, configuration);
private JsonUnitRequestMatchers(Path path, Configuration configuration, Function<Object, Object> jsonTransformer) {
super(path, configuration, jsonTransformer);
}

@NotNull
@Override
RequestMatcher matcher(@NotNull BiConsumer<Object, InternalMatcher> matcher) {
return new JsonRequestMatcher(path, configuration, matcher);
RequestMatcher matcher(@NotNull Consumer<InternalMatcher> matcher) {
return new JsonRequestMatcher(path, configuration, matcher, jsonTransformer);
}

@Override
@NotNull
JsonUnitRequestMatchers matchers(@NotNull Path path, @NotNull Configuration configuration) {
return new JsonUnitRequestMatchers(path, configuration);
JsonUnitRequestMatchers matchers(@NotNull Path path, @NotNull Configuration configuration, @NotNull Function<Object, Object> jsonTransformer) {
return new JsonUnitRequestMatchers(path, configuration, jsonTransformer);
}

/**
* Creates JsonUnitResultMatchers to be used for JSON assertions.
*/
@NotNull
public static JsonUnitRequestMatchers json() {
return new JsonUnitRequestMatchers(Path.root(), Configuration.empty());
return new JsonUnitRequestMatchers(Path.root(), Configuration.empty(), Function.identity());
}

private static class JsonRequestMatcher extends AbstractSpringMatcher implements RequestMatcher {
private JsonRequestMatcher(
@NotNull Path path,
@NotNull Configuration configuration,
@NotNull BiConsumer<Object, InternalMatcher> matcher) {
super(path, configuration, matcher);
@NotNull Consumer<InternalMatcher> matcher,
@NotNull Function<Object, Object> jsonTransformer) {
super(path, configuration, matcher, jsonTransformer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
Expand All @@ -36,35 +38,37 @@
* </code>
*/
public class JsonUnitResultMatchers extends AbstractSpringMatchers<JsonUnitResultMatchers, ResultMatcher> {
private JsonUnitResultMatchers(Path path, Configuration configuration) {
super(path, configuration);
private JsonUnitResultMatchers(Path path, Configuration configuration, Function<Object, Object> jsonTransformer) {
super(path, configuration, jsonTransformer);
}

/**
* Creates JsonUnitResultMatchers to be used for JSON assertions.
*/
public static JsonUnitResultMatchers json() {
return new JsonUnitResultMatchers(Path.root(), Configuration.empty());
return new JsonUnitResultMatchers(Path.root(), Configuration.empty(), Function.identity());
}

@Override
@NotNull
ResultMatcher matcher(@NotNull BiConsumer<Object, InternalMatcher> matcher) {
return new JsonResultMatcher(path, configuration, matcher);
ResultMatcher matcher(@NotNull Consumer<InternalMatcher> matcher) {
return new JsonResultMatcher(path, configuration, matcher, jsonTransformer);
}

@Override
@NotNull
JsonUnitResultMatchers matchers(@NotNull Path path, @NotNull Configuration configuration) {
return new JsonUnitResultMatchers(path, configuration);
JsonUnitResultMatchers matchers(@NotNull Path path, @NotNull Configuration configuration, @NotNull Function<Object, Object> jsonTransformer) {
return new JsonUnitResultMatchers(path, configuration, jsonTransformer);
}

private static class JsonResultMatcher extends AbstractSpringMatcher implements ResultMatcher {
private JsonResultMatcher(
@NotNull Path path,
@NotNull Configuration configuration,
@NotNull BiConsumer<Object, InternalMatcher> matcher) {
super(path, configuration, matcher);
@NotNull Consumer<InternalMatcher> matcher,
@NotNull Function<Object, Object> jsonTransformer
) {
super(path, configuration, matcher, jsonTransformer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.internal.Path;
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
Expand All @@ -22,33 +23,35 @@
*/
public class WebTestClientJsonMatcher
extends AbstractSpringMatchers<WebTestClientJsonMatcher, Consumer<EntityExchangeResult<byte[]>>> {
private WebTestClientJsonMatcher(Path path, Configuration configuration) {
super(path, configuration);
private WebTestClientJsonMatcher(Path path, Configuration configuration, Function<Object, Object> jsonTransformer) {
super(path, configuration, jsonTransformer);
}

public static WebTestClientJsonMatcher json() {
return new WebTestClientJsonMatcher(Path.root(), Configuration.empty());
return new WebTestClientJsonMatcher(Path.root(), Configuration.empty(), Function.identity());
}

@Override
@NotNull
Consumer<EntityExchangeResult<byte[]>> matcher(@NotNull BiConsumer<Object, InternalMatcher> matcher) {
return new JsonUnitWebTestClientMatcher(path, configuration, matcher);
Consumer<EntityExchangeResult<byte[]>> matcher(@NotNull Consumer<InternalMatcher> matcher) {
return new JsonUnitWebTestClientMatcher(path, configuration, matcher, jsonTransformer);
}

@Override
@NotNull
WebTestClientJsonMatcher matchers(@NotNull Path path, @NotNull Configuration configuration) {
return new WebTestClientJsonMatcher(path, configuration);
WebTestClientJsonMatcher matchers(@NotNull Path path, @NotNull Configuration configuration, @NotNull Function<Object, Object> jsonTransformer) {
return new WebTestClientJsonMatcher(path, configuration, jsonTransformer);
}

private static class JsonUnitWebTestClientMatcher extends AbstractSpringMatcher
implements Consumer<EntityExchangeResult<byte[]>> {
private JsonUnitWebTestClientMatcher(
@NotNull Path path,
@NotNull Configuration configuration,
@NotNull BiConsumer<Object, InternalMatcher> matcher) {
super(path, configuration, matcher);
@NotNull Consumer<InternalMatcher> matcher,
@NotNull Function<Object, Object> jsonTransformer
) {
super(path, configuration, matcher, jsonTransformer);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.Option;
import net.javacrumbs.jsonunit.spring.testit.demo.ExampleController;
import org.junit.jupiter.api.Test;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
Expand All @@ -24,13 +25,14 @@ void shouldWorkWithMockMvcTester() {
}

@Test
void shouldUseConvertToJAckson() {
void shouldUseConvertToJackson() {
MockMvcTester mvc = MockMvcTester.of(new ExampleController())
.withHttpMessageConverters(singleton(new MappingJackson2HttpMessageConverter()));
assertThat(mvc.get().uri("/sample"))
.hasStatusOk()
.bodyJson()
.convertTo(jsonUnitJson())
.when(Option.IGNORING_ARRAY_ORDER)
.inPath("result.array")
.isArray()
.containsExactly(1, 2, 3);
Expand Down
Loading

0 comments on commit 6266fbc

Please sign in to comment.