Browse Source

Introduce empty & non-empty JsonPath matchers

This commit introduces new `isEmpty()` and `isNotEmpty()` methods in
`JsonPathResultMatchers` and `JsonPathRequestMatchers` which delegate
to the new `assertValueIsEmpty()` and `assertValueIsNotEmpty()` methods
in `JsonPathExpectationsHelper`, respectively.

Issue: SPR-13352
pull/859/head
Sam Brannen 9 years ago
parent
commit
7a17abe448
  1. 48
      spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java
  2. 38
      spring-test/src/main/java/org/springframework/test/web/client/match/JsonPathRequestMatchers.java
  3. 40
      spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java
  4. 141
      spring-test/src/test/java/org/springframework/test/util/JsonPathExpectationsHelperTests.java
  5. 70
      spring-test/src/test/java/org/springframework/test/web/client/match/JsonPathRequestMatchersTests.java
  6. 70
      spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

48
spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java

@ -25,7 +25,9 @@ import java.util.Map; @@ -25,7 +25,9 @@ import java.util.Map;
import org.hamcrest.Matcher;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.JsonPath;
@ -135,8 +137,7 @@ public class JsonPathExpectationsHelper { @@ -135,8 +137,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsString(String content) throws ParseException {
Object value = assertExistsAndReturn(content);
String reason = "Expected a string at JSON path \"" + this.expression + "\" but found: " + value;
assertThat(reason, value, instanceOf(String.class));
assertThat(failureReason("a string", value), value, instanceOf(String.class));
}
/**
@ -147,8 +148,7 @@ public class JsonPathExpectationsHelper { @@ -147,8 +148,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsBoolean(String content) throws ParseException {
Object value = assertExistsAndReturn(content);
String reason = "Expected a boolean at JSON path \"" + this.expression + "\" but found: " + value;
assertThat(reason, value, instanceOf(Boolean.class));
assertThat(failureReason("a boolean", value), value, instanceOf(Boolean.class));
}
/**
@ -159,8 +159,7 @@ public class JsonPathExpectationsHelper { @@ -159,8 +159,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsNumber(String content) throws ParseException {
Object value = assertExistsAndReturn(content);
String reason = "Expected a number at JSON path \"" + this.expression + "\" but found: " + value;
assertThat(reason, value, instanceOf(Number.class));
assertThat(failureReason("a number", value), value, instanceOf(Number.class));
}
/**
@ -170,8 +169,7 @@ public class JsonPathExpectationsHelper { @@ -170,8 +169,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsArray(String content) throws ParseException {
Object value = assertExistsAndReturn(content);
String reason = "Expected an array at JSON path \"" + this.expression + "\" but found: " + value;
assertThat(reason, value, instanceOf(List.class));
assertThat(failureReason("an array", value), value, instanceOf(List.class));
}
/**
@ -182,8 +180,7 @@ public class JsonPathExpectationsHelper { @@ -182,8 +180,7 @@ public class JsonPathExpectationsHelper {
*/
public void assertValueIsMap(String content) throws ParseException {
Object value = assertExistsAndReturn(content);
String reason = "Expected a map at JSON path \"" + this.expression + "\" but found: " + value;
assertThat(reason, value, instanceOf(Map.class));
assertThat(failureReason("a map", value), value, instanceOf(Map.class));
}
/**
@ -214,7 +211,7 @@ public class JsonPathExpectationsHelper { @@ -214,7 +211,7 @@ public class JsonPathExpectationsHelper {
catch (AssertionError ex) {
return;
}
String reason = "Expected no value at JSON path \"" + this.expression + "\" but found: " + value;
String reason = failureReason("no value", value);
if (pathIsIndefinite() && value instanceof List) {
assertTrue(reason, ((List<?>) value).isEmpty());
}
@ -223,6 +220,35 @@ public class JsonPathExpectationsHelper { @@ -223,6 +220,35 @@ public class JsonPathExpectationsHelper {
}
}
/**
* Evaluate the JSON path expression against the supplied {@code content}
* and assert that an empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link ObjectUtils#isEmpty(Object)}.
* @param content the JSON content
*/
public void assertValueIsEmpty(String content) throws ParseException {
Object value = evaluateJsonPath(content);
assertTrue(failureReason("an empty value", value), ObjectUtils.isEmpty(value));
}
/**
* Evaluate the JSON path expression against the supplied {@code content}
* and assert that a non-empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link ObjectUtils#isEmpty(Object)}.
* @param content the JSON content
*/
public void assertValueIsNotEmpty(String content) throws ParseException {
Object value = evaluateJsonPath(content);
assertTrue(failureReason("a non-empty value", value), !ObjectUtils.isEmpty(value));
}
private String failureReason(String expectedDescription, Object value) {
return String.format("Expected %s at JSON path \"%s\" but found: %s", expectedDescription, this.expression,
ObjectUtils.nullSafeToString(StringUtils.quoteIfString(value)));
}
private Object evaluateJsonPath(String content) throws ParseException {
String message = "No value at JSON path \"" + this.expression + "\", exception: ";
try {

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

@ -115,6 +115,44 @@ public class JsonPathRequestMatchers { @@ -115,6 +115,44 @@ public class JsonPathRequestMatchers {
};
}
/**
* Evaluate the JSON path expression against the request content and
* assert that an empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link org.springframework.util.ObjectUtils#isEmpty(Object)}.
* @since 4.2.1
* @see #isNotEmpty()
* @see #exists()
* @see #doesNotExist()
*/
public RequestMatcher isEmpty() {
return new AbstractJsonPathRequestMatcher() {
@Override
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsEmpty(request.getBodyAsString());
}
};
}
/**
* Evaluate the JSON path expression against the request content and
* assert that a non-empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link org.springframework.util.ObjectUtils#isEmpty(Object)}.
* @since 4.2.1
* @see #isEmpty()
* @see #exists()
* @see #doesNotExist()
*/
public RequestMatcher isNotEmpty() {
return new AbstractJsonPathRequestMatcher() {
@Override
public void matchInternal(MockClientHttpRequest request) throws IOException, ParseException {
JsonPathRequestMatchers.this.jsonPathHelper.assertValueIsNotEmpty(request.getBodyAsString());
}
};
}
/**
* Evaluate the JSON path expression against the request content and
* assert that the result is a {@link String}.

40
spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java

@ -116,6 +116,46 @@ public class JsonPathResultMatchers { @@ -116,6 +116,46 @@ public class JsonPathResultMatchers {
};
}
/**
* Evaluate the JSON path expression against the response content and
* assert that an empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link org.springframework.util.ObjectUtils#isEmpty(Object)}.
* @since 4.2.1
* @see #isNotEmpty()
* @see #exists()
* @see #doesNotExist()
*/
public ResultMatcher isEmpty() {
return new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
JsonPathResultMatchers.this.jsonPathHelper.assertValueIsEmpty(content);
}
};
}
/**
* Evaluate the JSON path expression against the response content and
* assert that a non-empty value exists at the given path.
* <p>For the semantics of <em>empty</em>, consult the Javadoc for
* {@link org.springframework.util.ObjectUtils#isEmpty(Object)}.
* @since 4.2.1
* @see #isEmpty()
* @see #exists()
* @see #doesNotExist()
*/
public ResultMatcher isNotEmpty() {
return new ResultMatcher() {
@Override
public void match(MvcResult result) throws Exception {
String content = result.getResponse().getContentAsString();
JsonPathResultMatchers.this.jsonPathHelper.assertValueIsNotEmpty(content);
}
};
}
/**
* Evaluate the JSON path expression against the response content and
* assert that the result is a {@link String}.

141
spring-test/src/test/java/org/springframework/test/util/JsonPathExpectationsHelperTests.java

@ -32,13 +32,15 @@ import static org.hamcrest.CoreMatchers.*; @@ -32,13 +32,15 @@ import static org.hamcrest.CoreMatchers.*;
public class JsonPathExpectationsHelperTests {
private static final String CONTENT = "{" + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'emptyArray': [], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'emptyMap': {} " + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'whitespace': ' ', " + //
"'emptyString': '', " + //
"'emptyArray': [], " + //
"'emptyMap': {} " + //
"}";
private static final String SIMPSONS = "{ 'familyMembers': [ " + //
@ -113,8 +115,106 @@ public class JsonPathExpectationsHelperTests { @@ -113,8 +115,106 @@ public class JsonPathExpectationsHelperTests {
@Test
public void doesNotExistForIndefinatePathWithEmptyResults() throws Exception {
new JsonPathExpectationsHelper("$.familyMembers[?(@.name == 'Dilbert')]").doesNotExist(SIMPSONS);
}
@Test
public void assertValueIsEmptyForAnEmptyString() throws Exception {
new JsonPathExpectationsHelper("$.emptyString").assertValueIsEmpty(CONTENT);
}
@Test
public void assertValueIsEmptyForAnEmptyArray() throws Exception {
new JsonPathExpectationsHelper("$.emptyArray").assertValueIsEmpty(CONTENT);
}
@Test
public void assertValueIsEmptyForAnEmptyMap() throws Exception {
new JsonPathExpectationsHelper("$.emptyMap").assertValueIsEmpty(CONTENT);
}
@Test
public void assertValueIsEmptyForIndefinatePathWithEmptyResults() throws Exception {
new JsonPathExpectationsHelper("$.familyMembers[?(@.name == 'Dilbert')]").assertValueIsEmpty(SIMPSONS);
}
@Test
public void assertValueIsEmptyForIndefinatePathWithResults() throws Exception {
String expression = "$.familyMembers[?(@.name == 'Bart')]";
exception.expect(AssertionError.class);
exception.expectMessage("Expected an empty value at JSON path \"" + expression
+ "\" but found: [{\"name\":\"Bart\"}]");
new JsonPathExpectationsHelper(expression).assertValueIsEmpty(SIMPSONS);
}
@Test
public void assertValueIsEmptyForWhitespace() throws Exception {
String expression = "$.whitespace";
exception.expect(AssertionError.class);
exception.expectMessage("Expected an empty value at JSON path \"" + expression + "\" but found: ' '");
new JsonPathExpectationsHelper(expression).assertValueIsEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForString() throws Exception {
new JsonPathExpectationsHelper("$.str").assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForNumber() throws Exception {
new JsonPathExpectationsHelper("$.num").assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForBoolean() throws Exception {
new JsonPathExpectationsHelper("$.bool").assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForArray() throws Exception {
new JsonPathExpectationsHelper("$.arr").assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForMap() throws Exception {
new JsonPathExpectationsHelper("$.colorMap").assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForIndefinatePathWithResults() throws Exception {
new JsonPathExpectationsHelper("$.familyMembers[?(@.name == 'Bart')]").assertValueIsNotEmpty(SIMPSONS);
}
@Test
public void assertValueIsNotEmptyForIndefinatePathWithEmptyResults() throws Exception {
String expression = "$.familyMembers[?(@.name == 'Dilbert')]";
new JsonPathExpectationsHelper(expression).doesNotExist(SIMPSONS);
exception.expect(AssertionError.class);
exception.expectMessage("Expected a non-empty value at JSON path \"" + expression + "\" but found: []");
new JsonPathExpectationsHelper(expression).assertValueIsNotEmpty(SIMPSONS);
}
@Test
public void assertValueIsNotEmptyForAnEmptyString() throws Exception {
String expression = "$.emptyString";
exception.expect(AssertionError.class);
exception.expectMessage("Expected a non-empty value at JSON path \"" + expression + "\" but found: ''");
new JsonPathExpectationsHelper(expression).assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForAnEmptyArray() throws Exception {
String expression = "$.emptyArray";
exception.expect(AssertionError.class);
exception.expectMessage("Expected a non-empty value at JSON path \"" + expression + "\" but found: []");
new JsonPathExpectationsHelper(expression).assertValueIsNotEmpty(CONTENT);
}
@Test
public void assertValueIsNotEmptyForAnEmptyMap() throws Exception {
String expression = "$.emptyMap";
exception.expect(AssertionError.class);
exception.expectMessage("Expected a non-empty value at JSON path \"" + expression + "\" but found: {}");
new JsonPathExpectationsHelper(expression).assertValueIsNotEmpty(CONTENT);
}
@Test
@ -134,10 +234,17 @@ public class JsonPathExpectationsHelperTests { @@ -134,10 +234,17 @@ public class JsonPathExpectationsHelperTests {
new JsonPathExpectationsHelper("$.str").assertValueIsString(CONTENT);
}
@Test
public void assertValueIsStringForAnEmptyString() throws Exception {
new JsonPathExpectationsHelper("$.emptyString").assertValueIsString(CONTENT);
}
@Test
public void assertValueIsStringForNonString() throws Exception {
String expression = "$.bool";
exception.expect(AssertionError.class);
new JsonPathExpectationsHelper("$.bool").assertValueIsString(CONTENT);
exception.expectMessage("Expected a string at JSON path \"" + expression + "\" but found: true");
new JsonPathExpectationsHelper(expression).assertValueIsString(CONTENT);
}
@Test
@ -147,8 +254,10 @@ public class JsonPathExpectationsHelperTests { @@ -147,8 +254,10 @@ public class JsonPathExpectationsHelperTests {
@Test
public void assertValueIsNumberForNonNumber() throws Exception {
String expression = "$.bool";
exception.expect(AssertionError.class);
new JsonPathExpectationsHelper("$.bool").assertValueIsNumber(CONTENT);
exception.expectMessage("Expected a number at JSON path \"" + expression + "\" but found: true");
new JsonPathExpectationsHelper(expression).assertValueIsNumber(CONTENT);
}
@Test
@ -158,8 +267,10 @@ public class JsonPathExpectationsHelperTests { @@ -158,8 +267,10 @@ public class JsonPathExpectationsHelperTests {
@Test
public void assertValueIsBooleanForNonBoolean() throws Exception {
String expression = "$.num";
exception.expect(AssertionError.class);
new JsonPathExpectationsHelper("$.num").assertValueIsBoolean(CONTENT);
exception.expectMessage("Expected a boolean at JSON path \"" + expression + "\" but found: 5");
new JsonPathExpectationsHelper(expression).assertValueIsBoolean(CONTENT);
}
@Test
@ -174,8 +285,10 @@ public class JsonPathExpectationsHelperTests { @@ -174,8 +285,10 @@ public class JsonPathExpectationsHelperTests {
@Test
public void assertValueIsArrayForNonArray() throws Exception {
String expression = "$.str";
exception.expect(AssertionError.class);
new JsonPathExpectationsHelper("$.str").assertValueIsArray(CONTENT);
exception.expectMessage("Expected an array at JSON path \"" + expression + "\" but found: 'foo'");
new JsonPathExpectationsHelper(expression).assertValueIsArray(CONTENT);
}
@Test
@ -190,8 +303,10 @@ public class JsonPathExpectationsHelperTests { @@ -190,8 +303,10 @@ public class JsonPathExpectationsHelperTests {
@Test
public void assertValueIsMapForNonMap() throws Exception {
String expression = "$.str";
exception.expect(AssertionError.class);
new JsonPathExpectationsHelper("$.str").assertValueIsMap(CONTENT);
exception.expectMessage("Expected a map at JSON path \"" + expression + "\" but found: 'foo'");
new JsonPathExpectationsHelper(expression).assertValueIsMap(CONTENT);
}
}

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

@ -33,13 +33,14 @@ import static org.hamcrest.CoreMatchers.*; @@ -33,13 +33,14 @@ import static org.hamcrest.CoreMatchers.*;
public class JsonPathRequestMatchersTests {
private static final String REQUEST_CONTENT = "{" + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'emptyArray': [], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'emptyMap': {} " + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'emptyString': '', " + //
"'emptyArray': [], " + //
"'emptyMap': {} " + //
"}";
private static final MockClientHttpRequest request = new MockClientHttpRequest();
@ -114,6 +115,61 @@ public class JsonPathRequestMatchersTests { @@ -114,6 +115,61 @@ public class JsonPathRequestMatchersTests {
new JsonPathRequestMatchers("$.emptyMap").doesNotExist().match(request);
}
@Test
public void isEmptyForAnEmptyString() throws Exception {
new JsonPathRequestMatchers("$.emptyString").isEmpty().match(request);
}
@Test
public void isEmptyForAnEmptyArray() throws Exception {
new JsonPathRequestMatchers("$.emptyArray").isEmpty().match(request);
}
@Test
public void isEmptyForAnEmptyMap() throws Exception {
new JsonPathRequestMatchers("$.emptyMap").isEmpty().match(request);
}
@Test
public void isNotEmptyForString() throws Exception {
new JsonPathRequestMatchers("$.str").isNotEmpty().match(request);
}
@Test
public void isNotEmptyForNumber() throws Exception {
new JsonPathRequestMatchers("$.num").isNotEmpty().match(request);
}
@Test
public void isNotEmptyForBoolean() throws Exception {
new JsonPathRequestMatchers("$.bool").isNotEmpty().match(request);
}
@Test
public void isNotEmptyForArray() throws Exception {
new JsonPathRequestMatchers("$.arr").isNotEmpty().match(request);
}
@Test
public void isNotEmptyForMap() throws Exception {
new JsonPathRequestMatchers("$.colorMap").isNotEmpty().match(request);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyString() throws Exception {
new JsonPathRequestMatchers("$.emptyString").isNotEmpty().match(request);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyArray() throws Exception {
new JsonPathRequestMatchers("$.emptyArray").isNotEmpty().match(request);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyMap() throws Exception {
new JsonPathRequestMatchers("$.emptyMap").isNotEmpty().match(request);
}
@Test
public void isArray() throws Exception {
new JsonPathRequestMatchers("$.arr").isArray().match(request);

70
spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

@ -33,13 +33,14 @@ import org.springframework.test.web.servlet.StubMvcResult; @@ -33,13 +33,14 @@ import org.springframework.test.web.servlet.StubMvcResult;
public class JsonPathResultMatchersTests {
private static final String RESPONSE_CONTENT = "{" + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'emptyArray': [], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'emptyMap': {} " + //
"'str': 'foo', " + //
"'num': 5, " + //
"'bool': true, " + //
"'arr': [42], " + //
"'colorMap': {'red': 'rojo'}, " + //
"'emptyString': '', " + //
"'emptyArray': [], " + //
"'emptyMap': {} " + //
"}";
private static final StubMvcResult stubMvcResult;
@ -117,6 +118,61 @@ public class JsonPathResultMatchersTests { @@ -117,6 +118,61 @@ public class JsonPathResultMatchersTests {
new JsonPathResultMatchers("$.emptyMap").doesNotExist().match(stubMvcResult);
}
@Test
public void isEmptyForAnEmptyString() throws Exception {
new JsonPathResultMatchers("$.emptyString").isEmpty().match(stubMvcResult);
}
@Test
public void isEmptyForAnEmptyArray() throws Exception {
new JsonPathResultMatchers("$.emptyArray").isEmpty().match(stubMvcResult);
}
@Test
public void isEmptyForAnEmptyMap() throws Exception {
new JsonPathResultMatchers("$.emptyMap").isEmpty().match(stubMvcResult);
}
@Test
public void isNotEmptyForString() throws Exception {
new JsonPathResultMatchers("$.str").isNotEmpty().match(stubMvcResult);
}
@Test
public void isNotEmptyForNumber() throws Exception {
new JsonPathResultMatchers("$.num").isNotEmpty().match(stubMvcResult);
}
@Test
public void isNotEmptyForBoolean() throws Exception {
new JsonPathResultMatchers("$.bool").isNotEmpty().match(stubMvcResult);
}
@Test
public void isNotEmptyForArray() throws Exception {
new JsonPathResultMatchers("$.arr").isNotEmpty().match(stubMvcResult);
}
@Test
public void isNotEmptyForMap() throws Exception {
new JsonPathResultMatchers("$.colorMap").isNotEmpty().match(stubMvcResult);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyString() throws Exception {
new JsonPathResultMatchers("$.emptyString").isNotEmpty().match(stubMvcResult);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyArray() throws Exception {
new JsonPathResultMatchers("$.emptyArray").isNotEmpty().match(stubMvcResult);
}
@Test(expected = AssertionError.class)
public void isNotEmptyForAnEmptyMap() throws Exception {
new JsonPathResultMatchers("$.emptyMap").isNotEmpty().match(stubMvcResult);
}
@Test
public void isArray() throws Exception {
new JsonPathResultMatchers("$.arr").isArray().match(stubMvcResult);

Loading…
Cancel
Save