Skip to content

Commit 68463e2

Browse files
committed
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
1 parent 6fa9539 commit 68463e2

File tree

7 files changed

+72
-26
lines changed

7 files changed

+72
-26
lines changed

Diff for: spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -237,22 +237,22 @@ private String failureReason(String expectedDescription, Object value) {
237237
}
238238

239239
private Object evaluateJsonPath(String content) {
240-
String message = "No value at JSON path \"" + this.expression + "\", exception: ";
241240
try {
242241
return this.jsonPath.read(content);
243242
}
244243
catch (Throwable ex) {
245-
throw new AssertionError(message + ex.getMessage());
244+
String message = "No value at JSON path \"" + this.expression + "\"";
245+
throw new AssertionError(message, ex);
246246
}
247247
}
248248

249249
private Object evaluateJsonPath(String content, Class<?> targetType) {
250-
String message = "No value at JSON path \"" + this.expression + "\", exception: ";
251250
try {
252251
return JsonPath.parse(content).read(this.expression, targetType);
253252
}
254253
catch (Throwable ex) {
255-
throw new AssertionError(message + ex.getMessage());
254+
String message = "No value at JSON path \"" + this.expression + "\"";
255+
throw new AssertionError(message, ex);
256256
}
257257
}
258258

Diff for: spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
3030
/**
3131
* Factory for assertions on the request content using
3232
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
33+
*
3334
* <p>An instance of this class is typically accessed via
3435
* {@link MockRestRequestMatchers#jsonPath(String, Matcher)} or
3536
* {@link MockRestRequestMatchers#jsonPath(String, Object...)}.
@@ -70,10 +71,11 @@ protected void matchInternal(MockClientHttpRequest request) throws IOException,
7071
}
7172

7273
/**
73-
* An overloaded variant of (@link {@link #value(Matcher)} that also
74-
* accepts a target type for the resulting value that the matcher can work
75-
* reliably against. This can be useful for matching numbers reliably for
76-
* example coercing an integer into a double.
74+
* An overloaded variant of {@link #value(Matcher)} that also accepts a
75+
* target type for the resulting value that the matcher can work reliably
76+
* against.
77+
* <p>This can be useful for matching numbers reliably &mdash; for example,
78+
* to coerce an integer into a double.
7779
* @since 4.3.3
7880
*/
7981
public <T> RequestMatcher value(final Matcher<T> matcher, final Class<T> targetType) {

Diff for: spring-test/src/main/java/org/springframework/test/web/client/match/MockRestRequestMatchers.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public static ContentRequestMatchers content() {
219219
* @param expression the JSON path optionally parameterized with arguments
220220
* @param args arguments to parameterize the JSON path expression with
221221
*/
222-
public static JsonPathRequestMatchers jsonPath(String expression, Object ... args) {
222+
public static JsonPathRequestMatchers jsonPath(String expression, Object... args) {
223223
return new JsonPathRequestMatchers(expression, args);
224224
}
225225

Diff for: spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -78,6 +78,8 @@ public JsonPathResultMatchers prefix(String prefix) {
7878
/**
7979
* Evaluate the JSON path expression against the response content and
8080
* assert the resulting value with the given Hamcrest {@link Matcher}.
81+
* @see #value(Matcher, Class)
82+
* @see #value(Object)
8183
*/
8284
public <T> ResultMatcher value(final Matcher<T> matcher) {
8385
return new ResultMatcher() {
@@ -89,9 +91,31 @@ public void match(MvcResult result) throws Exception {
8991
};
9092
}
9193

94+
/**
95+
* An overloaded variant of {@link #value(Matcher)} that also accepts a
96+
* target type for the resulting value that the matcher can work reliably
97+
* against.
98+
* <p>This can be useful for matching numbers reliably &mdash; for example,
99+
* to coerce an integer into a double.
100+
* @since 4.3.15
101+
* @see #value(Matcher)
102+
* @see #value(Object)
103+
*/
104+
public <T> ResultMatcher value(Matcher<T> matcher, Class<T> targetType) {
105+
return new ResultMatcher() {
106+
@Override
107+
public void match(MvcResult result) throws Exception {
108+
String content = getContent(result);
109+
jsonPathHelper.assertValue(content, matcher, targetType);
110+
}
111+
};
112+
}
113+
92114
/**
93115
* Evaluate the JSON path expression against the response content and
94116
* assert that the result is equal to the supplied value.
117+
* @see #value(Matcher)
118+
* @see #value(Matcher, Class)
95119
*/
96120
public ResultMatcher value(final Object expectedValue) {
97121
return new ResultMatcher() {

Diff for: spring-test/src/main/java/org/springframework/test/web/servlet/result/MockMvcResultMatchers.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -176,7 +176,7 @@ public static ContentResultMatchers content() {
176176
* @param expression the JSON path expression, optionally parameterized with arguments
177177
* @param args arguments to parameterize the JSON path expression with
178178
*/
179-
public static JsonPathResultMatchers jsonPath(String expression, Object ... args) {
179+
public static JsonPathResultMatchers jsonPath(String expression, Object... args) {
180180
return new JsonPathResultMatchers(expression, args);
181181
}
182182

Diff for: spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,23 +55,33 @@ public class JsonPathRequestMatchersTests {
5555
}
5656

5757

58+
@Test(expected = AssertionError.class)
59+
public void valueWithMismatch() throws Exception {
60+
new JsonPathRequestMatchers("$.str").value("bogus").match(request);
61+
}
62+
5863
@Test
59-
public void value() throws Exception {
64+
public void valueWithDirectMatch() throws Exception {
6065
new JsonPathRequestMatchers("$.str").value("foo").match(request);
6166
}
6267

63-
@Test(expected = AssertionError.class)
64-
public void valueNoMatch() throws Exception {
65-
new JsonPathRequestMatchers("$.str").value("bogus").match(request);
68+
@Test // SPR-14498
69+
public void valueWithNumberConversion() throws Exception {
70+
new JsonPathRequestMatchers("$.num").value(5.0f).match(request);
6671
}
6772

6873
@Test
6974
public void valueWithMatcher() throws Exception {
7075
new JsonPathRequestMatchers("$.str").value(equalTo("foo")).match(request);
7176
}
7277

78+
@Test // SPR-14498
79+
public void valueWithMatcherAndNumberConversion() throws Exception {
80+
new JsonPathRequestMatchers("$.num").value(equalTo(5.0f), Float.class).match(request);
81+
}
82+
7383
@Test(expected = AssertionError.class)
74-
public void valueWithMatcherNoMatch() throws Exception {
84+
public void valueWithMatcherAndMismatch() throws Exception {
7585
new JsonPathRequestMatchers("$.str").value(equalTo("bogus")).match(request);
7686
}
7787

Diff for: spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,23 +58,33 @@ public class JsonPathResultMatchersTests {
5858
}
5959
}
6060

61+
@Test(expected = AssertionError.class)
62+
public void valueWithMismatch() throws Exception {
63+
new JsonPathResultMatchers("$.str").value("bogus").match(stubMvcResult);
64+
}
65+
6166
@Test
62-
public void value() throws Exception {
67+
public void valueWithDirectMatch() throws Exception {
6368
new JsonPathResultMatchers("$.str").value("foo").match(stubMvcResult);
6469
}
6570

66-
@Test(expected = AssertionError.class)
67-
public void valueNoMatch() throws Exception {
68-
new JsonPathResultMatchers("$.str").value("bogus").match(stubMvcResult);
71+
@Test // SPR-16587
72+
public void valueWithNumberConversion() throws Exception {
73+
new JsonPathResultMatchers("$.num").value(5.0f).match(stubMvcResult);
6974
}
7075

7176
@Test
7277
public void valueWithMatcher() throws Exception {
7378
new JsonPathResultMatchers("$.str").value(Matchers.equalTo("foo")).match(stubMvcResult);
7479
}
7580

81+
@Test // SPR-16587
82+
public void valueWithMatcherAndNumberConversion() throws Exception {
83+
new JsonPathResultMatchers("$.num").value(Matchers.equalTo(5.0f), Float.class).match(stubMvcResult);
84+
}
85+
7686
@Test(expected = AssertionError.class)
77-
public void valueWithMatcherNoMatch() throws Exception {
87+
public void valueWithMatcherAndMismatch() throws Exception {
7888
new JsonPathResultMatchers("$.str").value(Matchers.equalTo("bogus")).match(stubMvcResult);
7989
}
8090

0 commit comments

Comments
 (0)