Skip to content

Commit 4799668

Browse files
committed
Introduce additional JsonPath RequestMatchers in Spring MVC Test
Commit fffdd1e introduced additional JsonPath result matchers in JsonPathResultMatchers for server-side testing of MVC controllers. This commit introduces comparable methods in JsonPathRequestMatchers for client-side testing with a RestTemplate. - isString() - isBoolean() - isNumber() - isMap() Issue: SPR-13320
1 parent e4f386a commit 4799668

File tree

3 files changed

+159
-45
lines changed

3 files changed

+159
-45
lines changed

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,48 @@ protected void matchInternal(MockClientHttpRequest request) throws IOException,
115115
};
116116
}
117117

118+
/**
119+
* Evaluate the JSON path expression against the request content and
120+
* assert that the result is a {@link String}.
121+
* @since 4.2.1
122+
*/
123+
public RequestMatcher isString() {
124+
return new AbstractJsonPathRequestMatcher() {
125+
@Override
126+
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
127+
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsString(request.getBodyAsString());
128+
}
129+
};
130+
}
131+
132+
/**
133+
* Evaluate the JSON path expression against the request content and
134+
* assert that the result is a {@link Boolean}.
135+
* @since 4.2.1
136+
*/
137+
public RequestMatcher isBoolean() {
138+
return new AbstractJsonPathRequestMatcher() {
139+
@Override
140+
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
141+
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsBoolean(request.getBodyAsString());
142+
}
143+
};
144+
}
145+
146+
/**
147+
* Evaluate the JSON path expression against the request content and
148+
* assert that the result is a {@link Number}.
149+
* @since 4.2.1
150+
*/
151+
public RequestMatcher isNumber() {
152+
return new AbstractJsonPathRequestMatcher() {
153+
@Override
154+
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
155+
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsNumber(request.getBodyAsString());
156+
}
157+
};
158+
}
159+
118160
/**
119161
* Evaluate the JSON path expression against the request content and
120162
* assert that the result is an array.
@@ -128,6 +170,20 @@ protected void matchInternal(MockClientHttpRequest request) throws IOException,
128170
};
129171
}
130172

173+
/**
174+
* Evaluate the JSON path expression against the request content and
175+
* assert that the result is a {@link java.util.Map}.
176+
* @since 4.2.1
177+
*/
178+
public RequestMatcher isMap() {
179+
return new AbstractJsonPathRequestMatcher() {
180+
@Override
181+
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
182+
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsMap(request.getBodyAsString());
183+
}
184+
};
185+
}
186+
131187

132188
/**
133189
* Abstract base class for {@code JsonPath}-based {@link RequestMatcher}s.

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,49 @@ public void isArrayNoMatch() throws Exception {
129129
new JsonPathRequestMatchers("$.str").isArray().match(request);
130130
}
131131

132+
@Test
133+
public void isMap() throws Exception {
134+
new JsonPathRequestMatchers("$.colorMap").isMap().match(request);
135+
}
136+
137+
@Test
138+
public void isMapForAnEmptyMap() throws Exception {
139+
new JsonPathRequestMatchers("$.emptyMap").isMap().match(request);
140+
}
141+
142+
@Test(expected = AssertionError.class)
143+
public void isMapNoMatch() throws Exception {
144+
new JsonPathRequestMatchers("$.str").isMap().match(request);
145+
}
146+
147+
@Test
148+
public void isBoolean() throws Exception {
149+
new JsonPathRequestMatchers("$.bool").isBoolean().match(request);
150+
}
151+
152+
@Test(expected = AssertionError.class)
153+
public void isBooleanNoMatch() throws Exception {
154+
new JsonPathRequestMatchers("$.str").isBoolean().match(request);
155+
}
156+
157+
@Test
158+
public void isNumber() throws Exception {
159+
new JsonPathRequestMatchers("$.num").isNumber().match(request);
160+
}
161+
162+
@Test(expected = AssertionError.class)
163+
public void isNumberNoMatch() throws Exception {
164+
new JsonPathRequestMatchers("$.str").isNumber().match(request);
165+
}
166+
167+
@Test
168+
public void isString() throws Exception {
169+
new JsonPathRequestMatchers("$.str").isString().match(request);
170+
}
171+
172+
@Test(expected = AssertionError.class)
173+
public void isStringNoMatch() throws Exception {
174+
new JsonPathRequestMatchers("$.arr").isString().match(request);
175+
}
176+
132177
}

spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/JsonPathRequestMatchersIntegrationTests.java

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@
1717
package org.springframework.test.web.client.samples.matchers;
1818

1919
import java.net.URI;
20-
import java.util.ArrayList;
20+
import java.net.URISyntaxException;
2121
import java.util.Arrays;
22-
import java.util.List;
2322

24-
import org.junit.Before;
23+
import org.junit.After;
2524
import org.junit.Test;
2625

27-
import org.springframework.http.converter.HttpMessageConverter;
2826
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
2927
import org.springframework.test.web.Person;
3028
import org.springframework.test.web.client.MockRestServiceServer;
@@ -41,95 +39,75 @@
4139
* <a href="https://github.com/jayway/JsonPath">JsonPath</a> expressions.
4240
*
4341
* @author Rossen Stoyanchev
42+
* @author Sam Brannen
4443
* @see org.springframework.test.web.client.match.JsonPathRequestMatchers
44+
* @see org.springframework.test.web.client.match.JsonPathRequestMatchersTests
4545
*/
4646
public class JsonPathRequestMatchersIntegrationTests {
4747

48-
private MockRestServiceServer mockServer;
48+
private static final MultiValueMap<String, Person> people = new LinkedMultiValueMap<String, Person>();
4949

50-
private RestTemplate restTemplate;
51-
52-
private MultiValueMap<String, Person> people;
53-
54-
55-
@Before
56-
public void setup() {
57-
this.people = new LinkedMultiValueMap<String, Person>();
58-
this.people.add("composers", new Person("Johann Sebastian Bach"));
59-
this.people.add("composers", new Person("Johannes Brahms"));
60-
this.people.add("composers", new Person("Edvard Grieg"));
61-
this.people.add("composers", new Person("Robert Schumann"));
62-
this.people.add("performers", new Person("Vladimir Ashkenazy"));
63-
this.people.add("performers", new Person("Yehudi Menuhin"));
50+
static {
51+
people.add("composers", new Person("Johann Sebastian Bach"));
52+
people.add("composers", new Person("Johannes Brahms"));
53+
people.add("composers", new Person("Edvard Grieg"));
54+
people.add("composers", new Person("Robert Schumann"));
55+
people.add("performers", new Person("Vladimir Ashkenazy"));
56+
people.add("performers", new Person("Yehudi Menuhin"));
57+
}
6458

65-
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
66-
converters.add(new MappingJackson2HttpMessageConverter());
59+
private final RestTemplate restTemplate = new RestTemplate(Arrays.asList(new MappingJackson2HttpMessageConverter()));
6760

68-
this.restTemplate = new RestTemplate();
69-
this.restTemplate.setMessageConverters(converters);
61+
private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate);
7062

71-
this.mockServer = MockRestServiceServer.createServer(this.restTemplate);
72-
}
7363

7464
@Test
75-
public void testExists() throws Exception {
65+
public void exists() throws Exception {
7666
this.mockServer.expect(requestTo("/composers"))
7767
.andExpect(content().contentType("application/json;charset=UTF-8"))
7868
.andExpect(jsonPath("$.composers[0]").exists())
7969
.andExpect(jsonPath("$.composers[1]").exists())
8070
.andExpect(jsonPath("$.composers[2]").exists())
8171
.andExpect(jsonPath("$.composers[3]").exists())
8272
.andRespond(withSuccess());
83-
84-
this.restTemplate.put(new URI("/composers"), this.people);
85-
this.mockServer.verify();
8673
}
8774

8875
@Test
89-
public void testDoesNotExist() throws Exception {
76+
public void doesNotExist() throws Exception {
9077
this.mockServer.expect(requestTo("/composers"))
9178
.andExpect(content().contentType("application/json;charset=UTF-8"))
9279
.andExpect(jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist())
9380
.andExpect(jsonPath("$.composers[?(@.name == 'Robert Schuuuuuuman')]").doesNotExist())
9481
.andExpect(jsonPath("$.composers[-1]").doesNotExist())
9582
.andExpect(jsonPath("$.composers[4]").doesNotExist())
9683
.andRespond(withSuccess());
97-
98-
this.restTemplate.put(new URI("/composers"), this.people);
99-
this.mockServer.verify();
10084
}
10185

10286
@Test
103-
public void testEqualTo() throws Exception {
87+
public void value() throws Exception {
10488
this.mockServer.expect(requestTo("/composers"))
10589
.andExpect(content().contentType("application/json;charset=UTF-8"))
10690
.andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach"))
10791
.andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin"))
108-
.andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))) // Hamcrest
109-
.andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))) // Hamcrest
11092
.andRespond(withSuccess());
111-
112-
this.restTemplate.put(new URI("/composers"), this.people);
113-
this.mockServer.verify();
11493
}
11594

11695
@Test
117-
public void testHamcrestMatcher() throws Exception {
96+
public void hamcrestMatchers() throws Exception {
11897
this.mockServer.expect(requestTo("/composers"))
11998
.andExpect(content().contentType("application/json;charset=UTF-8"))
99+
.andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach")))
100+
.andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin")))
120101
.andExpect(jsonPath("$.composers[0].name", startsWith("Johann")))
121102
.andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy")))
122103
.andExpect(jsonPath("$.performers[1].name", containsString("di Me")))
123104
.andExpect(jsonPath("$.composers[1].name", isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))
124105
.andExpect(jsonPath("$.composers[:3].name", hasItem("Johannes Brahms")))
125106
.andRespond(withSuccess());
126-
127-
this.restTemplate.put(new URI("/composers"), this.people);
128-
this.mockServer.verify();
129107
}
130108

131109
@Test
132-
public void testHamcrestMatcherWithParameterizedJsonPath() throws Exception {
110+
public void hamcrestMatchersWithParameterizedJsonPaths() throws Exception {
133111
String composerName = "$.composers[%s].name";
134112
String performerName = "$.performers[%s].name";
135113

@@ -140,8 +118,43 @@ public void testHamcrestMatcherWithParameterizedJsonPath() throws Exception {
140118
.andExpect(jsonPath(performerName, 1).value(containsString("di Me")))
141119
.andExpect(jsonPath(composerName, 1).value(isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))))
142120
.andRespond(withSuccess());
121+
}
122+
123+
@Test
124+
public void isArray() throws Exception {
125+
this.mockServer.expect(requestTo("/composers"))
126+
.andExpect(content().contentType("application/json;charset=UTF-8"))
127+
.andExpect(jsonPath("$.composers").isArray())
128+
.andRespond(withSuccess());
129+
}
130+
131+
@Test
132+
public void isString() throws Exception {
133+
this.mockServer.expect(requestTo("/composers"))
134+
.andExpect(content().contentType("application/json;charset=UTF-8"))
135+
.andExpect(jsonPath("$.composers[0].name").isString())
136+
.andRespond(withSuccess());
137+
}
138+
139+
@Test
140+
public void isNumber() throws Exception {
141+
this.mockServer.expect(requestTo("/composers"))
142+
.andExpect(content().contentType("application/json;charset=UTF-8"))
143+
.andExpect(jsonPath("$.composers[0].someDouble").isNumber())
144+
.andRespond(withSuccess());
145+
}
146+
147+
@Test
148+
public void isBoolean() throws Exception {
149+
this.mockServer.expect(requestTo("/composers"))
150+
.andExpect(content().contentType("application/json;charset=UTF-8"))
151+
.andExpect(jsonPath("$.composers[0].someBoolean").isBoolean())
152+
.andRespond(withSuccess());
153+
}
143154

144-
this.restTemplate.put(new URI("/composers"), this.people);
155+
@After
156+
public void performRequestAndVerify() throws URISyntaxException {
157+
this.restTemplate.put(new URI("/composers"), people);
145158
this.mockServer.verify();
146159
}
147160

0 commit comments

Comments
 (0)