Add hasJsonPath and doesNotHaveJsonPath asserts
Extend `JsonContentAssert` with `hasJsonPath` and `doesNotHaveJsonPath`
methods which can be used to check the path regardless of the value it
may or may not contain.
Prior to this commit there wasn't an easy way to assert that the
Jackson `@JsonInclude(JsonInclude.Include.NON_NULL)` annotation was
applied since `assertDoesNotHavePathValue` would pass for both
`{"name" : null}` and `{}`.
Closes gh-17608
This commit is contained in:
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
|
||||
import com.jayway.jsonpath.Configuration;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
import com.jayway.jsonpath.PathNotFoundException;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractBooleanAssert;
|
||||
import org.assertj.core.api.AbstractCharSequenceAssert;
|
||||
@@ -748,6 +749,21 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
|
||||
return assertNotPassed(compare(expectedJson, comparator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the JSON path is present without checking if it has a value.
|
||||
* @param expression the {@link JsonPath} expression
|
||||
* @param args arguments to parameterize the {@code JsonPath} expression with, using
|
||||
* formatting specifiers defined in {@link String#format(String, Object...)}
|
||||
* @return {@code this} assertion object
|
||||
* @throws AssertionError if the value at the given path is missing
|
||||
* @since 2.2.0
|
||||
* @see #hasJsonPathValue(CharSequence, Object...)
|
||||
*/
|
||||
public JsonContentAssert hasJsonPath(CharSequence expression, Object... args) {
|
||||
new JsonPathValue(expression, args).assertHasPath();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the actual value at the given JSON path produces a non-null result. If
|
||||
* the JSON path expression is not {@linkplain JsonPath#isDefinite() definite}, this
|
||||
@@ -846,6 +862,21 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the JSON path is not present, even if it has a {@code null} value.
|
||||
* @param expression the {@link JsonPath} expression
|
||||
* @param args arguments to parameterize the {@code JsonPath} expression with, using
|
||||
* formatting specifiers defined in {@link String#format(String, Object...)}
|
||||
* @return {@code this} assertion object
|
||||
* @throws AssertionError if the value at the given path is not missing
|
||||
* @since 2.2.0
|
||||
* @see #doesNotHaveJsonPathValue(CharSequence, Object...)
|
||||
*/
|
||||
public JsonContentAssert doesNotHaveJsonPath(CharSequence expression, Object... args) {
|
||||
new JsonPathValue(expression, args).assertDoesNotHavePath();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the actual value at the given JSON path produces no result. If the JSON
|
||||
* path expression is not {@linkplain JsonPath#isDefinite() definite}, this method
|
||||
@@ -1049,6 +1080,24 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
|
||||
|
||||
}
|
||||
|
||||
void assertHasPath() {
|
||||
try {
|
||||
read();
|
||||
}
|
||||
catch (PathNotFoundException ex) {
|
||||
failWithMessage("No JSON path \"%s\" found", this.expression);
|
||||
}
|
||||
}
|
||||
|
||||
void assertDoesNotHavePath() {
|
||||
try {
|
||||
read();
|
||||
failWithMessage("Expecting no JSON path \"%s\"", this.expression);
|
||||
}
|
||||
catch (PathNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
void assertHasValue(Class<?> type, String expectedDescription) {
|
||||
Object value = getValue(true);
|
||||
if (value == null || isIndefiniteAndEmpty()) {
|
||||
@@ -1080,9 +1129,7 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
|
||||
|
||||
Object getValue(boolean required) {
|
||||
try {
|
||||
CharSequence json = JsonContentAssert.this.actual;
|
||||
return this.jsonPath.read((json != null) ? json.toString() : null,
|
||||
JsonContentAssert.this.configuration);
|
||||
return read();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (required) {
|
||||
@@ -1092,6 +1139,11 @@ public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSeq
|
||||
}
|
||||
}
|
||||
|
||||
private Object read() {
|
||||
CharSequence json = JsonContentAssert.this.actual;
|
||||
return this.jsonPath.read((json != null) ? json.toString() : null, JsonContentAssert.this.configuration);
|
||||
}
|
||||
|
||||
private String getNoValueMessage() {
|
||||
return "No value at JSON path \"" + this.expression + "\"";
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ class JsonContentAssertTests {
|
||||
|
||||
private static final String SIMPSONS = loadJson("simpsons.json");
|
||||
|
||||
private static final String NULLS = loadJson("nulls.json");
|
||||
|
||||
private static JSONComparator COMPARATOR = new DefaultComparator(JSONCompareMode.LENIENT);
|
||||
|
||||
@TempDir
|
||||
@@ -839,6 +841,24 @@ class JsonContentAssertTests {
|
||||
assertThat(forJson(SOURCE)).isNotEqualToJson(createResource(DIFFERENT), COMPARATOR);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathForPresentAndNotNull() {
|
||||
assertThat(forJson(NULLS)).hasJsonPath("valuename");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathForPresentAndNull() {
|
||||
assertThat(forJson(NULLS)).hasJsonPath("nullname");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathForNotPresent() {
|
||||
String expression = "missing";
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(forJson(NULLS)).hasJsonPath(expression))
|
||||
.withMessageContaining("No JSON path \"" + expression + "\" found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathValue() {
|
||||
assertThat(forJson(TYPES)).hasJsonPathValue("$.str");
|
||||
@@ -854,6 +874,22 @@ class JsonContentAssertTests {
|
||||
assertThat(forJson(TYPES)).hasJsonPathValue("$.emptyMap");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathValueForANullValue() {
|
||||
String expression = "nullname";
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(forJson(NULLS)).hasJsonPathValue(expression))
|
||||
.withMessageContaining("No value at JSON path \"" + expression + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathValueForMissingValue() {
|
||||
String expression = "missing";
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(forJson(NULLS)).hasJsonPathValue(expression))
|
||||
.withMessageContaining("No value at JSON path \"" + expression + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPathValueForIndefinitePathWithResults() {
|
||||
assertThat(forJson(SIMPSONS)).hasJsonPathValue("$.familyMembers[?(@.name == 'Bart')]");
|
||||
@@ -867,6 +903,27 @@ class JsonContentAssertTests {
|
||||
.withMessageContaining("No value at JSON path \"" + expression + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPathForMissing() {
|
||||
assertThat(forJson(NULLS)).doesNotHaveJsonPath("missing");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPathForNull() {
|
||||
String expression = "nullname";
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(forJson(NULLS)).doesNotHaveJsonPath(expression))
|
||||
.withMessageContaining("Expecting no JSON path \"" + expression + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPathForPresent() {
|
||||
String expression = "valuename";
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(forJson(NULLS)).doesNotHaveJsonPath(expression))
|
||||
.withMessageContaining("Expecting no JSON path \"" + expression + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPathValue() {
|
||||
assertThat(forJson(TYPES)).doesNotHaveJsonPathValue("$.bogus");
|
||||
@@ -902,6 +959,11 @@ class JsonContentAssertTests {
|
||||
assertThat(forJson(SIMPSONS)).doesNotHaveJsonPathValue("$.familyMembers[?(@.name == 'Dilbert')]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPathValueForNull() {
|
||||
assertThat(forJson(NULLS)).doesNotHaveJsonPathValue("nullname");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasEmptyJsonPathValueForAnEmptyString() {
|
||||
assertThat(forJson(TYPES)).hasEmptyJsonPathValue("$.emptyString");
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"valuename" : "spring",
|
||||
"nullname" : null
|
||||
}
|
||||
Reference in New Issue
Block a user