Skip to content

Commit

Permalink
Better error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
lukas-krecan committed Apr 12, 2022
1 parent b4d055d commit 0339d1e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,19 @@
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.OBJECT;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType.STRING;
import static net.javacrumbs.jsonunit.jsonpath.InternalJsonPathUtils.resolveJsonPaths;
import static org.assertj.core.description.Description.mostRelevantDescription;
import static org.assertj.core.util.Strings.isNullOrEmpty;

public class JsonAssert extends AbstractAssert<JsonAssert, Object> {
final Path path;
final Configuration configuration;
private final InternalMatcher internalMatcher;
private final Object actualForMatcher;

JsonAssert(Path path, Configuration configuration, Object actual, boolean alreadyParsed) {
super(alreadyParsed ? JsonUtils.wrapDeserializedObject(actual) : JsonUtils.convertToJson(actual, "actual"), JsonAssert.class);
this.path = path;
this.configuration = configuration;
this.internalMatcher = new InternalMatcher(alreadyParsed ? JsonUtils.wrapDeserializedObject(actual) : actual, path.asPrefix(), "", configuration);
this.actualForMatcher = alreadyParsed ? JsonUtils.wrapDeserializedObject(actual) : actual;
usingComparator(new JsonComparator(configuration, path, false));
}

Expand Down Expand Up @@ -148,7 +149,7 @@ public BigDecimalAssert isNumber() {
* Asserts that the value is an integer. 1 is an integer 1.0, 1.1, 1e3, 1e0, 1e-3 is not.
*/
public BigIntegerAssert isIntegralNumber() {
Node node = internalMatcher.assertIntegralNumber();
Node node = internalMatcher().assertIntegralNumber();
return new BigIntegerAssert(node.decimalValue().toBigIntegerExact())
.as("Different value found in node \"%s\"", path);
}
Expand All @@ -158,7 +159,7 @@ public BigIntegerAssert isIntegralNumber() {
*/
@NotNull
public BigDecimalAssert asNumber() {
internalMatcher.isPresent(NUMBER.getDescription());
internalMatcher().isPresent(NUMBER.getDescription());
Node node = getNode(actual, "");
if (node.getNodeType() == NUMBER) {
return createBigDecimalAssert(node.decimalValue());
Expand All @@ -169,7 +170,7 @@ public BigDecimalAssert asNumber() {
failWithMessage("Node \"" + path + "\" can not be converted to number expected: <a number> but was: <" + quoteTextValue(node.getValue()) + ">.");
}
} else {
internalMatcher.failOnType(node, "number or string");
internalMatcher().failOnType(node, "number or string");
}
return null;
}
Expand All @@ -178,6 +179,17 @@ private BigDecimalAssert createBigDecimalAssert(BigDecimal value) {
return new BigDecimalAssert(value).as("Different value found in node \"%s\"", path);
}

private InternalMatcher internalMatcher() {
String description = mostRelevantDescription(info.description(), "Node \"" + path + "\"");
return new InternalMatcher(
actualForMatcher,
path.asPrefix(),
"",
configuration,
description
);
}

/**
* Asserts that given node is present and is of type array.
*
Expand All @@ -187,7 +199,7 @@ private BigDecimalAssert createBigDecimalAssert(BigDecimal value) {
public JsonListAssert isArray() {
Node node = assertType(ARRAY);
return new JsonListAssert((List<?>)node.getValue(), path.asPrefix(), configuration)
.as("Different value found in node \"%s\"", path);
.as( "Node \"%s\"", path);
}

/**
Expand Down Expand Up @@ -244,15 +256,15 @@ public UriAssert isUri() {
*/
@NotNull
public JsonAssert isPresent() {
internalMatcher.isPresent();
internalMatcher().isPresent();
return this;
}

/**
* Asserts that given node is absent.
*/
public void isAbsent() {
internalMatcher.isAbsent();
internalMatcher().isAbsent();
}

/**
Expand All @@ -261,12 +273,12 @@ public void isAbsent() {
@Override
@NotNull
public JsonAssert isNotNull() {
internalMatcher.isNotNull();
internalMatcher().isNotNull();
return this;
}

private Node assertType(Node.NodeType type) {
return internalMatcher.assertType(type);
return internalMatcher().assertType(type);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,18 @@ public final class InternalMatcher {
private final Object actual;
private final String description;
private final Configuration configuration;
private String nodeDescription;


public InternalMatcher(@Nullable Object actual, @NotNull Path path, @NotNull String description, @NotNull Configuration configuration) {
public InternalMatcher(@Nullable Object actual, @NotNull Path path, @NotNull String description, @NotNull Configuration configuration, @NotNull String nodeDescription) {
this.path = path;
this.actual = actual;
this.description = description;
this.configuration = configuration;
this.nodeDescription = nodeDescription;
}

public InternalMatcher(@Nullable Object actual, @NotNull Path path, @NotNull String description, @NotNull Configuration configuration) {
this(actual, path, description, configuration, "Node \"" + path + "\"");
}

private InternalMatcher(@NotNull Object actual, @NotNull String pathPrefix) {
Expand Down Expand Up @@ -346,7 +351,7 @@ public void failOnType(@NotNull Node node, @NotNull String expectedType) {
}

private void failOnType(@NotNull String expectedType, @Nullable Object actualType) {
failWithMessage("Node \"" + path + "\" has invalid type, expected: <" + expectedType + "> but was: <" + actualType + ">.");
failWithMessage(nodeDescription + " has invalid type, expected: <" + expectedType + "> but was: <" + actualType + ">.");
}

/**
Expand All @@ -364,9 +369,9 @@ public void matches(@NotNull Matcher<?> matcher) {
}

@SuppressWarnings("unchecked")
private static void match(@NotNull Object value, @NotNull Path path, @NotNull Matcher<?> matcher) {
private void match(@NotNull Object value, @NotNull Path path, @NotNull Matcher<?> matcher) {
Node node = getNode(value, path);
assertThat("Node \"" + path + "\" does not match.", node.getValue(), (Matcher<? super Object>) matcher);
assertThat(nodeDescription + " does not match.", node.getValue(), (Matcher<? super Object>) matcher);
}


Expand All @@ -389,7 +394,7 @@ public class ArrayMatcher {
*/
public void ofLength(int expectedLength) {
if (array.size() != expectedLength) {
failWithMessage("Node \"" + path + "\" has invalid length, expected: <" + expectedLength + "> but was: <" + array.size() + ">.");
failWithMessage(nodeDescription + " has invalid length, expected: <" + expectedLength + "> but was: <" + array.size() + ">.");
}
}

Expand All @@ -402,18 +407,18 @@ public void thatContains(@Nullable Object expected) {
}
}

failWithMessage("Node \"" + path + "\" is '" + array + "', expected to contain '" + expected + "'.");
failWithMessage(nodeDescription + " is '" + array + "', expected to contain '" + expected + "'.");
}

public void isEmpty() {
if (!array.isEmpty()) {
failWithMessage("Node \"" + path + "\" is not an empty array.");
failWithMessage(nodeDescription + " is not an empty array.");
}
}

public void isNotEmpty() {
if (array.isEmpty()) {
failWithMessage("Node \"" + path + "\" is an empty array.");
failWithMessage(nodeDescription + " is an empty array.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ void compareJsonInJsonPathShallowArrayString() {
.inPath("$.root")
.isArray()
.containsExactly(value("450")))
.hasMessage("[Different value found in node \"$.root\"] \n" +
.hasMessage("[Node \"$.root\"] \n" +
"Expecting actual:\n" +
" [450]\n" +
"to contain exactly (and in same order):\n" +
Expand Down Expand Up @@ -591,7 +591,7 @@ void arraySimpleIgnoringOrderNotEqualComparison() {
void arraySimpleIgnoringOrderNotEqualComparisonError() {
assertThatThrownBy(() -> assertThatJson("{\"a\":[{\"b\": 1}, {\"c\": 1}, {\"d\": 1}]}").when(Option.IGNORING_ARRAY_ORDER).node("a").isArray()
.isNotEqualTo(json("[{\"c\": 1}, {\"b\": 1} ,{\"d\": 1}]")))
.hasMessage("[Different value found in node \"a\"] \n" +
.hasMessage("[Node \"a\"] \n" +
"Expecting:\n" +
" <[{\"b\":1}, {\"c\":1}, {\"d\":1}]>\n" +
"not to be equal to:\n" +
Expand Down Expand Up @@ -791,7 +791,7 @@ void arrayExtractingShouldFail() {
.isArray()
.extracting("id", "name")
.contains(tuple(valueOf(1), "{\"first\":\"Aaron\"}"), tuple(valueOf(2), "{\"first\":\"Paul\"}"))
).hasMessage("[Different value found in node \"\"] \n" +
).hasMessage("[Node \"\"] \n" +
"Expecting ArrayList:\n" +
" [(1, {\"first\":\"Aaron\"}), (2, {\"first\":\"John\"})]\n" +
"to contain:\n" +
Expand All @@ -811,7 +811,7 @@ void arrayExtractingShouldFailOnDifferentLengthTuple() {
.isArray()
.extracting("id", "name")
.contains(tuple(valueOf(1), "{\"first\":\"Aaron\"}", 3), tuple(valueOf(2), "{\"first\":\"John\"}"))
).hasMessage("[Different value found in node \"\"] \n" +
).hasMessage("[Node \"\"] \n" +
"Expecting ArrayList:\n" +
" [(1, {\"first\":\"Aaron\"}), (2, {\"first\":\"John\"})]\n" +
"to contain:\n" +
Expand All @@ -835,7 +835,7 @@ void elementWithTypeAssertShouldWork() {
String result = "{\"bundles\":[\"http://localhost:33621/rms/framework/bundle/0\"]}";
// FIXME: Better path in the message
assertThatThrownBy(() -> assertThatJson(result).node("bundles").isArray().element(0).isNumber())
.hasMessage("Node \"bundles\" has invalid type, expected: <number> but was: <\"http://localhost:33621/rms/framework/bundle/0\">.");
.hasMessage("Node \"bundles\" element at index 0 has invalid type, expected: <number> but was: <\"http://localhost:33621/rms/framework/bundle/0\">.");
}


Expand Down Expand Up @@ -1192,7 +1192,7 @@ void isArrayShouldFailIfItIsNotArray() {
@Test
void arrayOfLengthShouldFailOnIncorrectSize() {
assertThatThrownBy(() -> assertThatJson("{\"test\":[1,2,3]}").node("test").isArray().hasSize(2))
.hasMessage("[Different value found in node \"test\"] \n" +
.hasMessage("[Node \"test\"] \n" +
"Expected size: 2 but was: 3 in:\n" +
"[1, 2, 3]");
}
Expand Down Expand Up @@ -1267,7 +1267,7 @@ void positiveArrayIndexOutOfBounds() {
@Test
void arrayThatContainsShouldFailOnMissingNode() {
assertThatThrownBy(() -> assertThatJson("{\"test\":[{\"id\":36},{\"id\":37},{\"id\":38}]}").node("test").isArray().contains("{\"id\":42}"))
.hasMessage("[Different value found in node \"test\"] \n" +
.hasMessage("[Node \"test\"] \n" +
"Expecting JsonList:\n" +
" [{\"id\":36}, {\"id\":37}, {\"id\":38}]\n" +
"to contain:\n" +
Expand Down Expand Up @@ -1649,7 +1649,7 @@ protected void jsonPathShouldBeAbleToUseArrays() {
" \"price\": 8.96\n" +
" }"
)))
.hasMessage("[Different value found in node \"$.store.book\"] \n" +
.hasMessage("[Node \"$.store.book\"] \n" +
"Expecting JsonList:\n" +
" [{\"author\":\"Nigel Rees\",\"category\":\"reference\",\"price\":8.95,\"title\":\"Sayings of the Century\"},\n" +
" {\"author\":\"Evelyn Waugh\",\"category\":\"fiction\",\"price\":12.99,\"title\":\"Sword of Honour\"},\n" +
Expand Down

0 comments on commit 0339d1e

Please sign in to comment.