Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.groupbyinc.common.test.util.AssertUtils Maven / Gradle / Ivy
package com.groupbyinc.common.test.util;
import com.fasterxml.jackson.Mappers;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.thisptr.jackson.jq.JsonQuery;
import net.thisptr.jackson.jq.Scope;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.JSONCompare;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.skyscreamer.jsonassert.JSONCompareResult;
import org.skyscreamer.jsonassert.comparator.DefaultComparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class AssertUtils {
private static final transient Logger LOG = LoggerFactory.getLogger(AssertUtils.class);
private static final int JSON_SPACING = 4;
public static class LenientDoublesJsonComparator extends DefaultComparator {
private static final double MARGIN = 0.1;
private LenientDoublesJsonComparator() {
super(JSONCompareMode.STRICT);
}
private double parseMantissa(Number value) {
return Double.parseDouble(value.toString().split("E", 2)[0]);
}
private int parseExponent(Number value) {
String[] split = value.toString().split("E", 2);
return split.length < 2 ? 1 : Integer.parseInt(split[1]);
}
@Override
public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException {
if (expectedValue instanceof Number && actualValue instanceof Number) {
Number expectedNumber = ((Number) expectedValue);
Number actualNumber = ((Number) actualValue);
if (parseExponent(expectedNumber) != parseExponent(actualNumber) || Math.abs(parseMantissa(expectedNumber) - parseMantissa(actualNumber)) > MARGIN) {
result.fail(prefix, expectedValue, actualValue);
}
} else {
super.compareValues(prefix, expectedValue, actualValue, result);
}
}
}
private AssertUtils() {
// not publicly instantiable
}
public static > void assertListEqualsIgnoreOrder(List expected, List actual) {
Collections.sort(expected);
Collections.sort(actual);
assertEquals(expected, actual);
}
public static void assertJsonLinesEquals(List expectedLines, List actualLines) {
if (expectedLines.size() != actualLines.size()) {
fail("Expected line count: " + expectedLines.size() + " Actual line count: " + actualLines.size());
}
Collections.sort(expectedLines);
Collections.sort(actualLines);
for (int i = 0; i < expectedLines.size(); i++) {
assertJsonEquals(expectedLines.get(i), actualLines.get(i));
}
}
public static void assertJsonEquals(String expectedJson, Object actual) {
assertJsonEquals(".", expectedJson, actual);
}
public static void assertJsonEquals(String key, String expectedJson, Object actual) {
assertJsonEqualsWithMsg(null, key, expectedJson, actual);
}
public static void assertJsonEqualsWithMsg(String msg, String key, String expectedJson, Object actual) {
String actualJson = actual instanceof String ? (String) actual : Mappers.writeValueAsString(actual);
try {
if (StringUtils.isNotBlank(expectedJson) && StringUtils.isBlank(actualJson)) {
fail("no actual json received to compare to");
} else if (StringUtils.isBlank(expectedJson) && StringUtils.isNotBlank(actualJson)) {
fail("no expected json given to compare to");
}
boolean isArrayCheck = StringUtils.startsWith(expectedJson, "[");
boolean isValueCheck = !StringUtils.startsWith(expectedJson, "{");
JsonQuery jq = JsonQuery.compile(key + (isArrayCheck ? "[]" : ""));
ObjectMapper mapper = new ObjectMapper();
JsonNode actualJsonNode = mapper.readTree(actualJson);
List partials = jq.apply(Scope.newEmptyScope(), actualJsonNode).stream().map(p -> {
try {
return mapper.treeToValue(p, Object.class);
} catch (JsonProcessingException e) {
fail("unable to parse json" + e.getMessage());
return null;
}
}).collect(Collectors.toList());
if (CollectionUtils.isEmpty(partials)) {
fail("provided jq query does not match any partial json");
} else {
if (isArrayCheck) {
assertJsonArrayEquals(msg, expectedJson, mapper.writeValueAsString(partials));
} else if (isValueCheck) {
assertEquals(msg, expectedJson.replaceAll("\"", "'"), mapper.writeValueAsString(partials.get(0)).replaceAll("\"", "'"));
} else {
Map value = Mappers.getStrictReader(false).with(JsonParser.Feature.ALLOW_TRAILING_COMMA).forType(Map.class).readValue(expectedJson.getBytes());
JSONObject expected = new JSONObject(value);
JSONObject actualJsonObject = new JSONObject(mapper.writeValueAsString(partials.get(0)));
JSONCompareResult result = JSONCompare.compareJSON(expected, actualJsonObject, new LenientDoublesJsonComparator());
verifyJson(result, expected.toString(JSON_SPACING), actualJsonObject.toString(JSON_SPACING));
}
}
} catch (Exception e) {
LOG.warn("expected: {}\n actual: {}\n{}", expectedJson, actualJson, e.getMessage());
String errorMsg = "invalid expected json";
if (StringUtils.isNotBlank(msg)) {
errorMsg = ": " + msg;
}
fail(errorMsg + "\n expected: " + expectedJson);
}
}
private static void assertJsonArrayEquals(String msg, String expectedJson, Object actual) {
String actualJson = actual instanceof String ? (String) actual : Mappers.writeValueAsString(actual);
try {
List value = Mappers.getStrictReader(false).with(JsonParser.Feature.ALLOW_TRAILING_COMMA).forType(List.class).readValue(expectedJson.getBytes());
JSONArray expected = new JSONArray(value);
JSONArray actualArray = new JSONArray(actualJson);
JSONCompareResult result = JSONCompare.compareJSON(expected, actualArray, new LenientDoublesJsonComparator());
verifyJson(result, expected.toString(JSON_SPACING), actualArray.toString(JSON_SPACING));
} catch (Exception e) {
LOG.warn("expected: {}\n actual: {}\n{}", expectedJson, actualJson, e.getMessage());
String errorMsg = "invalid expected json";
if (StringUtils.isNotBlank(msg)) {
errorMsg = ": " + msg;
}
fail(errorMsg + "\n expected: " + expectedJson);
}
}
private static void verifyJson(JSONCompareResult result, String expectedFormatted, String actualFormatted) {
if (!result.passed()) {
assertEquals(String.format("expected: %s\n\nactual: %s\n\nmsg: %s\n", expectedFormatted, actualFormatted, result.getMessage()), expectedFormatted, actualFormatted);
assertTrue(result.passed());
}
}
public static void assertJsonEqualsWithMsg(String msg, String expectedJson, Object actual) {
assertJsonEqualsWithMsg(msg, ".", expectedJson, actual);
}
}