diff --git a/spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java b/spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java index a3bd2a487c0..969d28263b0 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java @@ -115,6 +115,48 @@ public class JsonPathRequestMatchers { }; } + /** + * Evaluate the JSON path expression against the request content and + * assert that the result is a {@link String}. + * @since 4.2.1 + */ + public RequestMatcher isString() { + return new AbstractJsonPathRequestMatcher() { + @Override + public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException { + JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsString(request.getBodyAsString()); + } + }; + } + + /** + * Evaluate the JSON path expression against the request content and + * assert that the result is a {@link Boolean}. + * @since 4.2.1 + */ + public RequestMatcher isBoolean() { + return new AbstractJsonPathRequestMatcher() { + @Override + public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException { + JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsBoolean(request.getBodyAsString()); + } + }; + } + + /** + * Evaluate the JSON path expression against the request content and + * assert that the result is a {@link Number}. + * @since 4.2.1 + */ + public RequestMatcher isNumber() { + return new AbstractJsonPathRequestMatcher() { + @Override + public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException { + JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsNumber(request.getBodyAsString()); + } + }; + } + /** * Evaluate the JSON path expression against the request content and * assert that the result is an array. @@ -128,6 +170,20 @@ public class JsonPathRequestMatchers { }; } + /** + * Evaluate the JSON path expression against the request content and + * assert that the result is a {@link java.util.Map}. + * @since 4.2.1 + */ + public RequestMatcher isMap() { + return new AbstractJsonPathRequestMatcher() { + @Override + public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException { + JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsMap(request.getBodyAsString()); + } + }; + } + /** * Abstract base class for {@code JsonPath}-based {@link RequestMatcher}s. diff --git a/spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java index 49623f77d4c..15e49150454 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java @@ -129,4 +129,49 @@ public class JsonPathRequestMatchersTests { new JsonPathRequestMatchers("$.str").isArray().match(request); } + @Test + public void isMap() throws Exception { + new JsonPathRequestMatchers("$.colorMap").isMap().match(request); + } + + @Test + public void isMapForAnEmptyMap() throws Exception { + new JsonPathRequestMatchers("$.emptyMap").isMap().match(request); + } + + @Test(expected = AssertionError.class) + public void isMapNoMatch() throws Exception { + new JsonPathRequestMatchers("$.str").isMap().match(request); + } + + @Test + public void isBoolean() throws Exception { + new JsonPathRequestMatchers("$.bool").isBoolean().match(request); + } + + @Test(expected = AssertionError.class) + public void isBooleanNoMatch() throws Exception { + new JsonPathRequestMatchers("$.str").isBoolean().match(request); + } + + @Test + public void isNumber() throws Exception { + new JsonPathRequestMatchers("$.num").isNumber().match(request); + } + + @Test(expected = AssertionError.class) + public void isNumberNoMatch() throws Exception { + new JsonPathRequestMatchers("$.str").isNumber().match(request); + } + + @Test + public void isString() throws Exception { + new JsonPathRequestMatchers("$.str").isString().match(request); + } + + @Test(expected = AssertionError.class) + public void isStringNoMatch() throws Exception { + new JsonPathRequestMatchers("$.arr").isString().match(request); + } + } diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/JsonPathRequestMatchersIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/JsonPathRequestMatchersIntegrationTests.java index e1aa5f998e4..dc0ca6db935 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/JsonPathRequestMatchersIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/samples/matchers/JsonPathRequestMatchersIntegrationTests.java @@ -17,14 +17,12 @@ package org.springframework.test.web.client.samples.matchers; import java.net.URI; -import java.util.ArrayList; +import java.net.URISyntaxException; import java.util.Arrays; -import java.util.List; -import org.junit.Before; +import org.junit.After; import org.junit.Test; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.test.web.Person; import org.springframework.test.web.client.MockRestServiceServer; @@ -41,38 +39,30 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat * JsonPath expressions. * * @author Rossen Stoyanchev + * @author Sam Brannen * @see org.springframework.test.web.client.match.JsonPathRequestMatchers + * @see org.springframework.test.web.client.match.JsonPathRequestMatchersTests */ public class JsonPathRequestMatchersIntegrationTests { - private MockRestServiceServer mockServer; + private static final MultiValueMap people = new LinkedMultiValueMap(); - private RestTemplate restTemplate; - - private MultiValueMap people; - - - @Before - public void setup() { - this.people = new LinkedMultiValueMap(); - this.people.add("composers", new Person("Johann Sebastian Bach")); - this.people.add("composers", new Person("Johannes Brahms")); - this.people.add("composers", new Person("Edvard Grieg")); - this.people.add("composers", new Person("Robert Schumann")); - this.people.add("performers", new Person("Vladimir Ashkenazy")); - this.people.add("performers", new Person("Yehudi Menuhin")); + static { + people.add("composers", new Person("Johann Sebastian Bach")); + people.add("composers", new Person("Johannes Brahms")); + people.add("composers", new Person("Edvard Grieg")); + people.add("composers", new Person("Robert Schumann")); + people.add("performers", new Person("Vladimir Ashkenazy")); + people.add("performers", new Person("Yehudi Menuhin")); + } - List> converters = new ArrayList>(); - converters.add(new MappingJackson2HttpMessageConverter()); + private final RestTemplate restTemplate = new RestTemplate(Arrays.asList(new MappingJackson2HttpMessageConverter())); - this.restTemplate = new RestTemplate(); - this.restTemplate.setMessageConverters(converters); + private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate); - this.mockServer = MockRestServiceServer.createServer(this.restTemplate); - } @Test - public void testExists() throws Exception { + public void exists() throws Exception { this.mockServer.expect(requestTo("/composers")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.composers[0]").exists()) @@ -80,13 +70,10 @@ public class JsonPathRequestMatchersIntegrationTests { .andExpect(jsonPath("$.composers[2]").exists()) .andExpect(jsonPath("$.composers[3]").exists()) .andRespond(withSuccess()); - - this.restTemplate.put(new URI("/composers"), this.people); - this.mockServer.verify(); } @Test - public void testDoesNotExist() throws Exception { + public void doesNotExist() throws Exception { this.mockServer.expect(requestTo("/composers")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist()) @@ -94,42 +81,33 @@ public class JsonPathRequestMatchersIntegrationTests { .andExpect(jsonPath("$.composers[-1]").doesNotExist()) .andExpect(jsonPath("$.composers[4]").doesNotExist()) .andRespond(withSuccess()); - - this.restTemplate.put(new URI("/composers"), this.people); - this.mockServer.verify(); } @Test - public void testEqualTo() throws Exception { + public void value() throws Exception { this.mockServer.expect(requestTo("/composers")) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.composers[0].name").value("Johann Sebastian Bach")) .andExpect(jsonPath("$.performers[1].name").value("Yehudi Menuhin")) - .andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))) // Hamcrest - .andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))) // Hamcrest .andRespond(withSuccess()); - - this.restTemplate.put(new URI("/composers"), this.people); - this.mockServer.verify(); } @Test - public void testHamcrestMatcher() throws Exception { + public void hamcrestMatchers() throws Exception { this.mockServer.expect(requestTo("/composers")) .andExpect(content().contentType("application/json;charset=UTF-8")) + .andExpect(jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))) + .andExpect(jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"))) .andExpect(jsonPath("$.composers[0].name", startsWith("Johann"))) .andExpect(jsonPath("$.performers[0].name", endsWith("Ashkenazy"))) .andExpect(jsonPath("$.performers[1].name", containsString("di Me"))) .andExpect(jsonPath("$.composers[1].name", isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))) .andExpect(jsonPath("$.composers[:3].name", hasItem("Johannes Brahms"))) .andRespond(withSuccess()); - - this.restTemplate.put(new URI("/composers"), this.people); - this.mockServer.verify(); } @Test - public void testHamcrestMatcherWithParameterizedJsonPath() throws Exception { + public void hamcrestMatchersWithParameterizedJsonPaths() throws Exception { String composerName = "$.composers[%s].name"; String performerName = "$.performers[%s].name"; @@ -140,8 +118,43 @@ public class JsonPathRequestMatchersIntegrationTests { .andExpect(jsonPath(performerName, 1).value(containsString("di Me"))) .andExpect(jsonPath(composerName, 1).value(isIn(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms")))) .andRespond(withSuccess()); + } + + @Test + public void isArray() throws Exception { + this.mockServer.expect(requestTo("/composers")) + .andExpect(content().contentType("application/json;charset=UTF-8")) + .andExpect(jsonPath("$.composers").isArray()) + .andRespond(withSuccess()); + } + + @Test + public void isString() throws Exception { + this.mockServer.expect(requestTo("/composers")) + .andExpect(content().contentType("application/json;charset=UTF-8")) + .andExpect(jsonPath("$.composers[0].name").isString()) + .andRespond(withSuccess()); + } + + @Test + public void isNumber() throws Exception { + this.mockServer.expect(requestTo("/composers")) + .andExpect(content().contentType("application/json;charset=UTF-8")) + .andExpect(jsonPath("$.composers[0].someDouble").isNumber()) + .andRespond(withSuccess()); + } + + @Test + public void isBoolean() throws Exception { + this.mockServer.expect(requestTo("/composers")) + .andExpect(content().contentType("application/json;charset=UTF-8")) + .andExpect(jsonPath("$.composers[0].someBoolean").isBoolean()) + .andRespond(withSuccess()); + } - this.restTemplate.put(new URI("/composers"), this.people); + @After + public void performRequestAndVerify() throws URISyntaxException { + this.restTemplate.put(new URI("/composers"), people); this.mockServer.verify(); }