2020import java .lang .reflect .Method ;
2121import java .text .ParseException ;
2222import java .util .List ;
23+ import java .util .Map ;
2324
24- import com .jayway .jsonpath .InvalidPathException ;
25- import com .jayway .jsonpath .JsonPath ;
2625import org .hamcrest .Matcher ;
2726
2827import org .springframework .util .Assert ;
2928import org .springframework .util .ReflectionUtils ;
3029
31- import static org .hamcrest .MatcherAssert .*;
32- import static org .springframework .test .util .AssertionErrors .*;
30+ import com .jayway .jsonpath .InvalidPathException ;
31+ import com .jayway .jsonpath .JsonPath ;
32+
33+ import static org .hamcrest .MatcherAssert .assertThat ;
34+ import static org .hamcrest .core .IsInstanceOf .instanceOf ;
35+ import static org .springframework .test .util .AssertionErrors .assertEquals ;
36+ import static org .springframework .test .util .AssertionErrors .assertTrue ;
37+ import static org .springframework .test .util .AssertionErrors .fail ;
3338
3439/**
3540 * A helper class for applying assertions via JSON path expressions.
3944 *
4045 * @author Rossen Stoyanchev
4146 * @author Juergen Hoeller
47+ * @author Craig Andrews
48+ * @author Sam Brannen
4249 * @since 3.2
4350 */
4451public class JsonPathExpectationsHelper {
@@ -69,92 +76,130 @@ public class JsonPathExpectationsHelper {
6976
7077
7178 /**
72- * Construct a new JsonPathExpectationsHelper.
73- * @param expression the JsonPath expression
74- * @param args arguments to parameterize the JSON path expression with
79+ * Construct a new {@code JsonPathExpectationsHelper} .
80+ * @param expression the {@link JsonPath} expression; never {@code null} or empty
81+ * @param args arguments to parameterize the {@code JsonPath} expression, with
7582 * formatting specifiers defined in {@link String#format(String, Object...)}
7683 */
7784 public JsonPathExpectationsHelper (String expression , Object ... args ) {
85+ Assert .hasText (expression , "expression must not be null or empty" );
7886 this .expression = String .format (expression , args );
7987 this .jsonPath = (JsonPath ) ReflectionUtils .invokeMethod (
8088 compileMethod , null , this .expression , emptyFilters );
8189 }
8290
8391
8492 /**
85- * Evaluate the JSON path and assert the resulting value with the given {@code Matcher}.
86- * @param content the response content
87- * @param matcher the matcher to assert on the resulting json path
93+ * Evaluate the JSON path expression against the supplied {@code content}
94+ * and assert the resulting value with the given {@code Matcher}.
95+ * @param content the JSON response content
96+ * @param matcher the matcher with which to assert the result
8897 */
8998 @ SuppressWarnings ("unchecked" )
9099 public <T > void assertValue (String content , Matcher <T > matcher ) throws ParseException {
91100 T value = (T ) evaluateJsonPath (content );
92- assertThat ("JSON path " + this .expression , value , matcher );
93- }
94-
95- private Object evaluateJsonPath (String content ) throws ParseException {
96- String message = "No value for JSON path: " + this .expression + ", exception: " ;
97- try {
98- return this .jsonPath .read (content );
99- }
100- catch (InvalidPathException ex ) {
101- throw new AssertionError (message + ex .getMessage ());
102- }
103- catch (ArrayIndexOutOfBoundsException ex ) {
104- throw new AssertionError (message + ex .getMessage ());
105- }
106- catch (IndexOutOfBoundsException ex ) {
107- throw new AssertionError (message + ex .getMessage ());
108- }
101+ assertThat ("JSON path \" " + this .expression + "\" " , value , matcher );
109102 }
110103
111104 /**
112- * Apply the JSON path and assert the resulting value.
105+ * Evaluate the JSON path expression against the supplied {@code content}
106+ * and assert that the result is equal to the expected value.
107+ * @param content the JSON response content
108+ * @param expectedValue the expected value
113109 */
114- public void assertValue (String responseContent , Object expectedValue ) throws ParseException {
115- Object actualValue = evaluateJsonPath (responseContent );
110+ public void assertValue (String content , Object expectedValue ) throws ParseException {
111+ Object actualValue = evaluateJsonPath (content );
116112 if ((actualValue instanceof List ) && !(expectedValue instanceof List )) {
117113 @ SuppressWarnings ("rawtypes" )
118114 List actualValueList = (List ) actualValue ;
119115 if (actualValueList .isEmpty ()) {
120116 fail ("No matching value for JSON path \" " + this .expression + "\" " );
121117 }
122118 if (actualValueList .size () != 1 ) {
123- fail ("Got a list of values " + actualValue + " instead of the value " + expectedValue );
119+ fail ("Got a list of values " + actualValue + " instead of the expected single value " + expectedValue );
124120 }
125121 actualValue = actualValueList .get (0 );
126122 }
127123 else if (actualValue != null && expectedValue != null ) {
128- assertEquals ("For JSON path " + this .expression + " type of value" ,
129- expectedValue .getClass (), actualValue .getClass ());
124+ assertEquals ("For JSON path \" " + this .expression + "\" , type of value" ,
125+ expectedValue .getClass (). getName () , actualValue .getClass (). getName ());
130126 }
131- assertEquals ("JSON path " + this .expression , expectedValue , actualValue );
127+ assertEquals ("JSON path \" " + this .expression + "\" " , expectedValue , actualValue );
128+ }
129+
130+ /**
131+ * Evaluate the JSON path expression against the supplied {@code content}
132+ * and assert that the resulting value is a {@link String}.
133+ * @param content the JSON response content
134+ * @since 4.2.1
135+ */
136+ public void assertValueIsString (String content ) throws ParseException {
137+ Object value = assertExistsAndReturn (content );
138+ String reason = "Expected string at JSON path " + this .expression + " but found " + value ;
139+ assertThat (reason , value , instanceOf (String .class ));
140+ }
141+
142+ /**
143+ * Evaluate the JSON path expression against the supplied {@code content}
144+ * and assert that the resulting value is a {@link Boolean}.
145+ * @param content the JSON response content
146+ * @since 4.2.1
147+ */
148+ public void assertValueIsBoolean (String content ) throws ParseException {
149+ Object value = assertExistsAndReturn (content );
150+ String reason = "Expected boolean at JSON path " + this .expression + " but found " + value ;
151+ assertThat (reason , value , instanceOf (Boolean .class ));
152+ }
153+
154+ /**
155+ * Evaluate the JSON path expression against the supplied {@code content}
156+ * and assert that the resulting value is a {@link Number}.
157+ * @param content the JSON response content
158+ * @since 4.2.1
159+ */
160+ public void assertValueIsNumber (String content ) throws ParseException {
161+ Object value = assertExistsAndReturn (content );
162+ String reason = "Expected number at JSON path " + this .expression + " but found " + value ;
163+ assertThat (reason , value , instanceOf (Number .class ));
132164 }
133165
134166 /**
135- * Apply the JSON path and assert the resulting value is an array.
167+ * Evaluate the JSON path expression against the supplied {@code content}
168+ * and assert that the resulting value is an array.
169+ * @param content the JSON response content
136170 */
137- public void assertValueIsArray (String responseContent ) throws ParseException {
138- Object actualValue = evaluateJsonPath (responseContent );
139- assertTrue ("No value for JSON path \" " + this .expression + "\" " , actualValue != null );
140- String reason = "Expected array at JSON path " + this .expression + " but found " + actualValue ;
141- assertTrue (reason , actualValue instanceof List );
171+ public void assertValueIsArray (String content ) throws ParseException {
172+ Object value = assertExistsAndReturn (content );
173+ String reason = "Expected array for JSON path \" " + this .expression + "\" but found " + value ;
174+ assertTrue (reason , value instanceof List );
142175 }
143176
144177 /**
145- * Evaluate the JSON path and assert the resulting content exists.
178+ * Evaluate the JSON path expression against the supplied {@code content}
179+ * and assert that the resulting value is a {@link Map}.
180+ * @param content the JSON response content
181+ * @since 4.2.1
182+ */
183+ public void assertValueIsMap (String content ) throws ParseException {
184+ Object value = assertExistsAndReturn (content );
185+ String reason = "Expected map at JSON path " + this .expression + " but found " + value ;
186+ assertThat (reason , value , instanceOf (Map .class ));
187+ }
188+
189+ /**
190+ * Evaluate the JSON path expression against the supplied {@code content}
191+ * and assert that the resulting value exists.
192+ * @param content the JSON response content
146193 */
147194 public void exists (String content ) throws ParseException {
148- Object value = evaluateJsonPath (content );
149- String reason = "No value for JSON path " + this .expression ;
150- assertTrue (reason , value != null );
151- if (List .class .isInstance (value )) {
152- assertTrue (reason , !((List <?>) value ).isEmpty ());
153- }
195+ assertExistsAndReturn (content );
154196 }
155197
156198 /**
157- * Evaluate the JSON path and assert it doesn't point to any content.
199+ * Evaluate the JSON path expression against the supplied {@code content}
200+ * and assert that the resulting value is empty (i.e., that a match for
201+ * the JSON path expression does not exist in the supplied content).
202+ * @param content the JSON response content
158203 */
159204 public void doesNotExist (String content ) throws ParseException {
160205 Object value ;
@@ -173,4 +218,30 @@ public void doesNotExist(String content) throws ParseException {
173218 }
174219 }
175220
221+ private Object evaluateJsonPath (String content ) throws ParseException {
222+ String message = "No value for JSON path \" " + this .expression + "\" , exception: " ;
223+ try {
224+ return this .jsonPath .read (content );
225+ }
226+ catch (InvalidPathException ex ) {
227+ throw new AssertionError (message + ex .getMessage ());
228+ }
229+ catch (ArrayIndexOutOfBoundsException ex ) {
230+ throw new AssertionError (message + ex .getMessage ());
231+ }
232+ catch (IndexOutOfBoundsException ex ) {
233+ throw new AssertionError (message + ex .getMessage ());
234+ }
235+ }
236+
237+ private Object assertExistsAndReturn (String content ) throws ParseException {
238+ Object value = evaluateJsonPath (content );
239+ String reason = "No value for JSON path \" " + this .expression + "\" " ;
240+ assertTrue (reason , value != null );
241+ if (List .class .isInstance (value )) {
242+ assertTrue (reason , !((List <?>) value ).isEmpty ());
243+ }
244+ return value ;
245+ }
246+
176247}
0 commit comments