Browse Source

Support target type in JsonPath assertions for MockMvc results

This commit picks up where SPR-14498 left off by adding support for an
explicit target type when using JsonPath to perform an assertion against
the response content using a Hamcrest Matcher.

Specifically, there is a new overloaded value(Matcher<T>, Class<T>)
method in JsonPathResultMatchers for use with Hamcrest matchers where
the target type (i.e., Class<T>) can be specified.

Issue: SPR-16587
pull/1740/merge
Sam Brannen 8 years ago
parent
commit
2c2ce55f47
  1. 6
      spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java
  2. 12
      spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java
  3. 2
      spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java
  4. 27
      spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java
  5. 4
      spring-test/src/main/java/org/springframework/test/web/servlet/result/MockMvcResultMatchers.java
  6. 24
      spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java
  7. 22
      spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

6
spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -282,21 +282,21 @@ public class JsonPathExpectationsHelper {
@Nullable @Nullable
private Object evaluateJsonPath(String content) { private Object evaluateJsonPath(String content) {
String message = "No value at JSON path \"" + this.expression + "\"";
try { try {
return this.jsonPath.read(content); return this.jsonPath.read(content);
} }
catch (Throwable ex) { catch (Throwable ex) {
String message = "No value at JSON path \"" + this.expression + "\"";
throw new AssertionError(message, ex); throw new AssertionError(message, ex);
} }
} }
private Object evaluateJsonPath(String content, Class<?> targetType) { private Object evaluateJsonPath(String content, Class<?> targetType) {
String message = "No value at JSON path \"" + this.expression + "\"";
try { try {
return JsonPath.parse(content).read(this.expression, targetType); return JsonPath.parse(content).read(this.expression, targetType);
} }
catch (Throwable ex) { catch (Throwable ex) {
String message = "No value at JSON path \"" + this.expression + "\"";
throw new AssertionError(message, ex); throw new AssertionError(message, ex);
} }
} }

12
spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -30,6 +30,7 @@ import org.springframework.test.web.client.RequestMatcher;
/** /**
* Factory for assertions on the request content using * Factory for assertions on the request content using
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions. * <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
*
* <p>An instance of this class is typically accessed via * <p>An instance of this class is typically accessed via
* {@link MockRestRequestMatchers#jsonPath(String, Matcher)} or * {@link MockRestRequestMatchers#jsonPath(String, Matcher)} or
* {@link MockRestRequestMatchers#jsonPath(String, Object...)}. * {@link MockRestRequestMatchers#jsonPath(String, Object...)}.
@ -70,10 +71,11 @@ public class JsonPathRequestMatchers {
} }
/** /**
* An overloaded variant of (@link {@link #value(Matcher)} that also * An overloaded variant of {@link #value(Matcher)} that also accepts a
* accepts a target type for the resulting value that the matcher can work * target type for the resulting value that the matcher can work reliably
* reliably against. This can be useful for matching numbers reliably for * against.
* example coercing an integer into a double. * <p>This can be useful for matching numbers reliably &mdash; for example,
* to coerce an integer into a double.
* @since 4.3.3 * @since 4.3.3
*/ */
public <T> RequestMatcher value(final Matcher<T> matcher, final Class<T> targetType) { public <T> RequestMatcher value(final Matcher<T> matcher, final Class<T> targetType) {

2
spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java

@ -199,7 +199,7 @@ public abstract class MockRestRequestMatchers {
* @param expression the JSON path optionally parameterized with arguments * @param expression the JSON path optionally parameterized with arguments
* @param args arguments to parameterize the JSON path expression with * @param args arguments to parameterize the JSON path expression with
*/ */
public static JsonPathRequestMatchers jsonPath(String expression, Object ... args) { public static JsonPathRequestMatchers jsonPath(String expression, Object... args) {
return new JsonPathRequestMatchers(expression, args); return new JsonPathRequestMatchers(expression, args);
} }

27
spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -80,19 +80,40 @@ public class JsonPathResultMatchers {
/** /**
* Evaluate the JSON path expression against the response content and * Evaluate the JSON path expression against the response content and
* assert the resulting value with the given Hamcrest {@link Matcher}. * assert the resulting value with the given Hamcrest {@link Matcher}.
* @see #value(Matcher, Class)
* @see #value(Object)
*/ */
public <T> ResultMatcher value(final Matcher<T> matcher) { public <T> ResultMatcher value(Matcher<T> matcher) {
return result -> { return result -> {
String content = getContent(result); String content = getContent(result);
jsonPathHelper.assertValue(content, matcher); jsonPathHelper.assertValue(content, matcher);
}; };
} }
/**
* An overloaded variant of {@link #value(Matcher)} that also accepts a
* target type for the resulting value that the matcher can work reliably
* against.
* <p>This can be useful for matching numbers reliably &mdash; for example,
* to coerce an integer into a double.
* @since 4.3.15
* @see #value(Matcher)
* @see #value(Object)
*/
public <T> ResultMatcher value(Matcher<T> matcher, Class<T> targetType) {
return result -> {
String content = getContent(result);
jsonPathHelper.assertValue(content, matcher, targetType);
};
}
/** /**
* Evaluate the JSON path expression against the response content and * Evaluate the JSON path expression against the response content and
* assert that the result is equal to the supplied value. * assert that the result is equal to the supplied value.
* @see #value(Matcher)
* @see #value(Matcher, Class)
*/ */
public ResultMatcher value(final Object expectedValue) { public ResultMatcher value(Object expectedValue) {
return result -> jsonPathHelper.assertValue(getContent(result), expectedValue); return result -> jsonPathHelper.assertValue(getContent(result), expectedValue);
} }

4
spring-test/src/main/java/org/springframework/test/web/servlet/result/MockMvcResultMatchers.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -186,7 +186,7 @@ public abstract class MockMvcResultMatchers {
* @param expression the JSON path expression, optionally parameterized with arguments * @param expression the JSON path expression, optionally parameterized with arguments
* @param args arguments to parameterize the JSON path expression with * @param args arguments to parameterize the JSON path expression with
*/ */
public static JsonPathResultMatchers jsonPath(String expression, Object ... args) { public static JsonPathResultMatchers jsonPath(String expression, Object... args) {
return new JsonPathResultMatchers(expression, args); return new JsonPathResultMatchers(expression, args);
} }

24
spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package org.springframework.test.web.client.match;
import java.io.IOException; import java.io.IOException;
import org.hamcrest.Matchers;
import org.junit.Test; import org.junit.Test;
import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.mock.http.client.MockClientHttpRequest;
@ -55,14 +57,19 @@ public class JsonPathRequestMatchersTests {
} }
@Test(expected = AssertionError.class)
public void valueWithMismatch() throws Exception {
new JsonPathRequestMatchers("$.str").value("bogus").match(request);
}
@Test @Test
public void value() throws Exception { public void valueWithDirectMatch() throws Exception {
new JsonPathRequestMatchers("$.str").value("foo").match(request); new JsonPathRequestMatchers("$.str").value("foo").match(request);
} }
@Test(expected = AssertionError.class) @Test // SPR-14498
public void valueNoMatch() throws Exception { public void valueWithNumberConversion() throws Exception {
new JsonPathRequestMatchers("$.str").value("bogus").match(request); new JsonPathRequestMatchers("$.num").value(5.0f).match(request);
} }
@Test @Test
@ -70,8 +77,13 @@ public class JsonPathRequestMatchersTests {
new JsonPathRequestMatchers("$.str").value(equalTo("foo")).match(request); new JsonPathRequestMatchers("$.str").value(equalTo("foo")).match(request);
} }
@Test // SPR-14498
public void valueWithMatcherAndNumberConversion() throws Exception {
new JsonPathRequestMatchers("$.num").value(Matchers.equalTo(5.0f), Float.class).match(request);
}
@Test(expected = AssertionError.class) @Test(expected = AssertionError.class)
public void valueWithMatcherNoMatch() throws Exception { public void valueWithMatcherAndMismatch() throws Exception {
new JsonPathRequestMatchers("$.str").value(equalTo("bogus")).match(request); new JsonPathRequestMatchers("$.str").value(equalTo("bogus")).match(request);
} }

22
spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -58,14 +58,19 @@ public class JsonPathResultMatchersTests {
} }
} }
@Test(expected = AssertionError.class)
public void valueWithMismatch() throws Exception {
new JsonPathResultMatchers("$.str").value("bogus").match(stubMvcResult);
}
@Test @Test
public void value() throws Exception { public void valueWithDirectMatch() throws Exception {
new JsonPathResultMatchers("$.str").value("foo").match(stubMvcResult); new JsonPathResultMatchers("$.str").value("foo").match(stubMvcResult);
} }
@Test(expected = AssertionError.class) @Test // SPR-16587
public void valueNoMatch() throws Exception { public void valueWithNumberConversion() throws Exception {
new JsonPathResultMatchers("$.str").value("bogus").match(stubMvcResult); new JsonPathResultMatchers("$.num").value(5.0f).match(stubMvcResult);
} }
@Test @Test
@ -73,8 +78,13 @@ public class JsonPathResultMatchersTests {
new JsonPathResultMatchers("$.str").value(Matchers.equalTo("foo")).match(stubMvcResult); new JsonPathResultMatchers("$.str").value(Matchers.equalTo("foo")).match(stubMvcResult);
} }
@Test // SPR-16587
public void valueWithMatcherAndNumberConversion() throws Exception {
new JsonPathResultMatchers("$.num").value(Matchers.equalTo(5.0f), Float.class).match(stubMvcResult);
}
@Test(expected = AssertionError.class) @Test(expected = AssertionError.class)
public void valueWithMatcherNoMatch() throws Exception { public void valueWithMatcherAndMismatch() throws Exception {
new JsonPathResultMatchers("$.str").value(Matchers.equalTo("bogus")).match(stubMvcResult); new JsonPathResultMatchers("$.str").value(Matchers.equalTo("bogus")).match(stubMvcResult);
} }

Loading…
Cancel
Save