|
|
|
|
@ -20,16 +20,21 @@ import java.lang.reflect.Array;
@@ -20,16 +20,21 @@ import java.lang.reflect.Array;
|
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
import java.text.ParseException; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
import com.jayway.jsonpath.InvalidPathException; |
|
|
|
|
import com.jayway.jsonpath.JsonPath; |
|
|
|
|
import org.hamcrest.Matcher; |
|
|
|
|
|
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
|
|
|
|
|
|
import static org.hamcrest.MatcherAssert.*; |
|
|
|
|
import static org.springframework.test.util.AssertionErrors.*; |
|
|
|
|
import com.jayway.jsonpath.InvalidPathException; |
|
|
|
|
import com.jayway.jsonpath.JsonPath; |
|
|
|
|
|
|
|
|
|
import static org.hamcrest.MatcherAssert.assertThat; |
|
|
|
|
import static org.hamcrest.core.IsInstanceOf.instanceOf; |
|
|
|
|
import static org.springframework.test.util.AssertionErrors.assertEquals; |
|
|
|
|
import static org.springframework.test.util.AssertionErrors.assertTrue; |
|
|
|
|
import static org.springframework.test.util.AssertionErrors.fail; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* A helper class for applying assertions via JSON path expressions. |
|
|
|
|
@ -39,6 +44,8 @@ import static org.springframework.test.util.AssertionErrors.*;
@@ -39,6 +44,8 @@ import static org.springframework.test.util.AssertionErrors.*;
|
|
|
|
|
* |
|
|
|
|
* @author Rossen Stoyanchev |
|
|
|
|
* @author Juergen Hoeller |
|
|
|
|
* @author Craig Andrews |
|
|
|
|
* @author Sam Brannen |
|
|
|
|
* @since 3.2 |
|
|
|
|
*/ |
|
|
|
|
public class JsonPathExpectationsHelper { |
|
|
|
|
@ -69,12 +76,13 @@ public class JsonPathExpectationsHelper {
@@ -69,12 +76,13 @@ public class JsonPathExpectationsHelper {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Construct a new JsonPathExpectationsHelper. |
|
|
|
|
* @param expression the JsonPath expression |
|
|
|
|
* @param args arguments to parameterize the JSON path expression with |
|
|
|
|
* Construct a new {@code JsonPathExpectationsHelper}. |
|
|
|
|
* @param expression the {@link JsonPath} expression; never {@code null} or empty |
|
|
|
|
* @param args arguments to parameterize the {@code JsonPath} expression, with |
|
|
|
|
* formatting specifiers defined in {@link String#format(String, Object...)} |
|
|
|
|
*/ |
|
|
|
|
public JsonPathExpectationsHelper(String expression, Object... args) { |
|
|
|
|
Assert.hasText(expression, "expression must not be null or empty"); |
|
|
|
|
this.expression = String.format(expression, args); |
|
|
|
|
this.jsonPath = (JsonPath) ReflectionUtils.invokeMethod( |
|
|
|
|
compileMethod, null, this.expression, emptyFilters); |
|
|
|
|
@ -82,37 +90,25 @@ public class JsonPathExpectationsHelper {
@@ -82,37 +90,25 @@ public class JsonPathExpectationsHelper {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path and assert the resulting value with the given {@code Matcher}. |
|
|
|
|
* @param content the response content |
|
|
|
|
* @param matcher the matcher to assert on the resulting json path |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert the resulting value with the given {@code Matcher}. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @param matcher the matcher with which to assert the result |
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public <T> void assertValue(String content, Matcher<T> matcher) throws ParseException { |
|
|
|
|
T value = (T) evaluateJsonPath(content); |
|
|
|
|
assertThat("JSON path " + this.expression, value, matcher); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object evaluateJsonPath(String content) throws ParseException { |
|
|
|
|
String message = "No value for JSON path: " + this.expression + ", exception: "; |
|
|
|
|
try { |
|
|
|
|
return this.jsonPath.read(content); |
|
|
|
|
} |
|
|
|
|
catch (InvalidPathException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
catch (ArrayIndexOutOfBoundsException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
catch (IndexOutOfBoundsException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
assertThat("JSON path \"" + this.expression + "\"", value, matcher); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Apply the JSON path and assert the resulting value. |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the result is equal to the expected value. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @param expectedValue the expected value |
|
|
|
|
*/ |
|
|
|
|
public void assertValue(String responseContent, Object expectedValue) throws ParseException { |
|
|
|
|
Object actualValue = evaluateJsonPath(responseContent); |
|
|
|
|
public void assertValue(String content, Object expectedValue) throws ParseException { |
|
|
|
|
Object actualValue = evaluateJsonPath(content); |
|
|
|
|
if ((actualValue instanceof List) && !(expectedValue instanceof List)) { |
|
|
|
|
@SuppressWarnings("rawtypes") |
|
|
|
|
List actualValueList = (List) actualValue; |
|
|
|
|
@ -120,41 +116,90 @@ public class JsonPathExpectationsHelper {
@@ -120,41 +116,90 @@ public class JsonPathExpectationsHelper {
|
|
|
|
|
fail("No matching value for JSON path \"" + this.expression + "\""); |
|
|
|
|
} |
|
|
|
|
if (actualValueList.size() != 1) { |
|
|
|
|
fail("Got a list of values " + actualValue + " instead of the value " + expectedValue); |
|
|
|
|
fail("Got a list of values " + actualValue + " instead of the expected single value " + expectedValue); |
|
|
|
|
} |
|
|
|
|
actualValue = actualValueList.get(0); |
|
|
|
|
} |
|
|
|
|
else if (actualValue != null && expectedValue != null) { |
|
|
|
|
assertEquals("For JSON path " + this.expression + " type of value", |
|
|
|
|
expectedValue.getClass(), actualValue.getClass()); |
|
|
|
|
assertEquals("For JSON path \"" + this.expression + "\", type of value", |
|
|
|
|
expectedValue.getClass().getName(), actualValue.getClass().getName()); |
|
|
|
|
} |
|
|
|
|
assertEquals("JSON path " + this.expression, expectedValue, actualValue); |
|
|
|
|
assertEquals("JSON path \"" + this.expression + "\"", expectedValue, actualValue); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is a {@link String}. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @since 4.2.1 |
|
|
|
|
*/ |
|
|
|
|
public void assertValueIsString(String content) throws ParseException { |
|
|
|
|
Object value = assertExistsAndReturn(content); |
|
|
|
|
String reason = "Expected string at JSON path " + this.expression + " but found " + value; |
|
|
|
|
assertThat(reason, value, instanceOf(String.class)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is a {@link Boolean}. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @since 4.2.1 |
|
|
|
|
*/ |
|
|
|
|
public void assertValueIsBoolean(String content) throws ParseException { |
|
|
|
|
Object value = assertExistsAndReturn(content); |
|
|
|
|
String reason = "Expected boolean at JSON path " + this.expression + " but found " + value; |
|
|
|
|
assertThat(reason, value, instanceOf(Boolean.class)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is a {@link Number}. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @since 4.2.1 |
|
|
|
|
*/ |
|
|
|
|
public void assertValueIsNumber(String content) throws ParseException { |
|
|
|
|
Object value = assertExistsAndReturn(content); |
|
|
|
|
String reason = "Expected number at JSON path " + this.expression + " but found " + value; |
|
|
|
|
assertThat(reason, value, instanceOf(Number.class)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Apply the JSON path and assert the resulting value is an array. |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is an array. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
*/ |
|
|
|
|
public void assertValueIsArray(String responseContent) throws ParseException { |
|
|
|
|
Object actualValue = evaluateJsonPath(responseContent); |
|
|
|
|
assertTrue("No value for JSON path \"" + this.expression + "\"", actualValue != null); |
|
|
|
|
String reason = "Expected array at JSON path " + this.expression + " but found " + actualValue; |
|
|
|
|
assertTrue(reason, actualValue instanceof List); |
|
|
|
|
public void assertValueIsArray(String content) throws ParseException { |
|
|
|
|
Object value = assertExistsAndReturn(content); |
|
|
|
|
String reason = "Expected array for JSON path \"" + this.expression + "\" but found " + value; |
|
|
|
|
assertTrue(reason, value instanceof List); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path and assert the resulting content exists. |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is a {@link Map}. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
* @since 4.2.1 |
|
|
|
|
*/ |
|
|
|
|
public void assertValueIsMap(String content) throws ParseException { |
|
|
|
|
Object value = assertExistsAndReturn(content); |
|
|
|
|
String reason = "Expected map at JSON path " + this.expression + " but found " + value; |
|
|
|
|
assertThat(reason, value, instanceOf(Map.class)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value exists. |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
*/ |
|
|
|
|
public void exists(String content) throws ParseException { |
|
|
|
|
Object value = evaluateJsonPath(content); |
|
|
|
|
String reason = "No value for JSON path " + this.expression; |
|
|
|
|
assertTrue(reason, value != null); |
|
|
|
|
if (List.class.isInstance(value)) { |
|
|
|
|
assertTrue(reason, !((List<?>) value).isEmpty()); |
|
|
|
|
} |
|
|
|
|
assertExistsAndReturn(content); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Evaluate the JSON path and assert it doesn't point to any content. |
|
|
|
|
* Evaluate the JSON path expression against the supplied {@code content} |
|
|
|
|
* and assert that the resulting value is empty (i.e., that a match for |
|
|
|
|
* the JSON path expression does not exist in the supplied content). |
|
|
|
|
* @param content the JSON response content |
|
|
|
|
*/ |
|
|
|
|
public void doesNotExist(String content) throws ParseException { |
|
|
|
|
Object value; |
|
|
|
|
@ -173,4 +218,30 @@ public class JsonPathExpectationsHelper {
@@ -173,4 +218,30 @@ public class JsonPathExpectationsHelper {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object evaluateJsonPath(String content) throws ParseException { |
|
|
|
|
String message = "No value for JSON path \"" + this.expression + "\", exception: "; |
|
|
|
|
try { |
|
|
|
|
return this.jsonPath.read(content); |
|
|
|
|
} |
|
|
|
|
catch (InvalidPathException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
catch (ArrayIndexOutOfBoundsException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
catch (IndexOutOfBoundsException ex) { |
|
|
|
|
throw new AssertionError(message + ex.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Object assertExistsAndReturn(String content) throws ParseException { |
|
|
|
|
Object value = evaluateJsonPath(content); |
|
|
|
|
String reason = "No value for JSON path \"" + this.expression + "\""; |
|
|
|
|
assertTrue(reason, value != null); |
|
|
|
|
if (List.class.isInstance(value)) { |
|
|
|
|
assertTrue(reason, !((List<?>) value).isEmpty()); |
|
|
|
|
} |
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|