1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.test.util;
18
19 import java.lang.reflect.Array;
20 import java.lang.reflect.Method;
21 import java.text.ParseException;
22 import java.util.List;
23
24 import com.jayway.jsonpath.InvalidPathException;
25 import com.jayway.jsonpath.JsonPath;
26 import org.hamcrest.Matcher;
27
28 import org.springframework.util.Assert;
29 import org.springframework.util.ReflectionUtils;
30
31 import static org.springframework.test.util.AssertionErrors.*;
32 import static org.springframework.test.util.MatcherAssertionErrors.*;
33
34
35
36
37
38
39
40
41
42
43
44 public class JsonPathExpectationsHelper {
45
46 private static Method compileMethod;
47
48 private static Object emptyFilters;
49
50 static {
51
52 for (Method candidate : JsonPath.class.getMethods()) {
53 if (candidate.getName().equals("compile")) {
54 Class<?>[] paramTypes = candidate.getParameterTypes();
55 if (paramTypes.length == 2 && paramTypes[0].equals(String.class) && paramTypes[1].isArray()) {
56 compileMethod = candidate;
57 emptyFilters = Array.newInstance(paramTypes[1].getComponentType(), 0);
58 break;
59 }
60 }
61 }
62 Assert.state(compileMethod != null, "Unexpected JsonPath API - no compile(String, ...) method found");
63 }
64
65
66 private final String expression;
67
68 private final JsonPath jsonPath;
69
70
71
72
73
74
75
76
77 public JsonPathExpectationsHelper(String expression, Object... args) {
78 this.expression = String.format(expression, args);
79 this.jsonPath = (JsonPath) ReflectionUtils.invokeMethod(
80 compileMethod, null, this.expression, emptyFilters);
81 }
82
83
84
85
86
87
88
89 @SuppressWarnings("unchecked")
90 public <T> void assertValue(String content, Matcher<T> matcher) throws ParseException {
91 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 }
109 }
110
111
112
113
114 public void assertValue(String responseContent, Object expectedValue) throws ParseException {
115 Object actualValue = evaluateJsonPath(responseContent);
116 if ((actualValue instanceof List) && !(expectedValue instanceof List)) {
117 @SuppressWarnings("rawtypes")
118 List actualValueList = (List) actualValue;
119 if (actualValueList.isEmpty()) {
120 fail("No matching value for JSON path \"" + this.expression + "\"");
121 }
122 if (actualValueList.size() != 1) {
123 fail("Got a list of values " + actualValue + " instead of the value " + expectedValue);
124 }
125 actualValue = actualValueList.get(0);
126 }
127 else if (actualValue != null && expectedValue != null) {
128 assertEquals("For JSON path " + this.expression + " type of value",
129 expectedValue.getClass(), actualValue.getClass());
130 }
131 assertEquals("JSON path " + this.expression, expectedValue, actualValue);
132 }
133
134
135
136
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);
142 }
143
144
145
146
147 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 }
154 }
155
156
157
158
159 public void doesNotExist(String content) throws ParseException {
160 Object value;
161 try {
162 value = evaluateJsonPath(content);
163 }
164 catch (AssertionError ex) {
165 return;
166 }
167 String reason = String.format("Expected no value for JSON path: %s but found: %s", this.expression, value);
168 if (List.class.isInstance(value)) {
169 assertTrue(reason, ((List<?>) value).isEmpty());
170 }
171 else {
172 assertTrue(reason, value == null);
173 }
174 }
175
176 }