Assertj json extension (#6039)
* Assertj json extension * Allow chained invocations * Rename --------- Co-authored-by: juan.marchionatto <juan.marchionatto@smilecdr.com>
This commit is contained in:
parent
90251b31ab
commit
bc8d873c7f
|
@ -0,0 +1,367 @@
|
|||
package ca.uhn.test.util;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Fail.fail;
|
||||
|
||||
/**
|
||||
* Assertj extension to ease testing json strings with few nested quoted strings
|
||||
*/
|
||||
public class AssertJson extends AbstractAssert<AssertJson, String> {
|
||||
|
||||
public AssertJson(String actual) {
|
||||
super(actual, AssertJson.class);
|
||||
}
|
||||
|
||||
public static AssertJson assertThat(String actual) {
|
||||
return new AssertJson(actual);
|
||||
}
|
||||
|
||||
public AssertJson hasPath(String thePath) {
|
||||
isNotNull();
|
||||
isNotEmpty(thePath);
|
||||
|
||||
Assertions.assertThat(isJsonObjStr(actual)).isTrue();
|
||||
Map<String, Object> actualMap = getMap(actual);
|
||||
Assertions.assertThat(actualMap).isNotNull();
|
||||
getPathMap(thePath);
|
||||
return this;
|
||||
}
|
||||
|
||||
private AssertJson isNotEmpty(String thePath) {
|
||||
Assertions.assertThat(thePath).isNotEmpty();
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssertJson hasKeys(String... theKeys) {
|
||||
isNotNull();
|
||||
|
||||
Map<String, Object> map = getMap(actual);
|
||||
Assertions.assertThat(map).isNotNull();
|
||||
|
||||
Assertions.assertThat(
|
||||
map.keySet()).containsAll(Arrays.asList(theKeys));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssertJson hasExactlyKeys(String... theKeys) {
|
||||
isNotNull();
|
||||
|
||||
Map<String, Object> map = getMap(actual);
|
||||
Assertions.assertThat(map).isNotNull();
|
||||
|
||||
Assertions.assertThat(
|
||||
map.keySet()).hasSameElementsAs(Arrays.asList(theKeys));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssertJson hasExactlyKeysWithValues(List<String> theKeys, List<? extends Serializable> theValues) {
|
||||
isNotNull();
|
||||
|
||||
if (!checkSizes(theKeys.size(), theValues.size())) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Map<String, Object> map = getMap(actual);
|
||||
Assertions.assertThat(map).isNotNull();
|
||||
|
||||
Assertions.assertThat(
|
||||
map.keySet()).hasSameElementsAs(theKeys);
|
||||
|
||||
for (int i = 0; i <theKeys.size(); i++) {
|
||||
hasKeyWithValue(theKeys.get(i), theValues.get(i));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public AssertJson hasKeyWithValue(String theKey, Object theExpectedValue) {
|
||||
isNotNull();
|
||||
|
||||
Map<String, Object> actualMap = getMap(actual);
|
||||
Assertions.assertThat(actualMap).isNotNull();
|
||||
Object actualValue = actualMap.get(theKey);
|
||||
|
||||
JsonTestTypes actualValueType = getType(actualValue);
|
||||
JsonTestTypes expectedValueType = getType(theExpectedValue);
|
||||
|
||||
if (actualValueType != expectedValueType) {
|
||||
fail(getDifferentTypesMessage(theKey, actualValueType, expectedValueType));
|
||||
}
|
||||
|
||||
if (isJsonObjStr(theExpectedValue)) {
|
||||
assertJsonObject(actualMap, theKey, theExpectedValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (isJsonList(theExpectedValue)) {
|
||||
assertJsonList(actualMap, theKey, theExpectedValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
Assertions.assertThat(actualMap)
|
||||
.extracting(theKey)
|
||||
.isEqualTo(theExpectedValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void assertJsonList(Map<String, Object> theActualMap, String theKey, Object theExpectedValue) {
|
||||
List<?> expectedValueList = getList((String) theExpectedValue);
|
||||
Assertions.assertThat(expectedValueList).isNotNull();
|
||||
|
||||
Assertions.assertThat(theActualMap.get(theKey)).isNotNull().isInstanceOf(Collection.class);
|
||||
List<?> actualValueList = (List<?>) theActualMap.get(theKey);
|
||||
|
||||
Assertions.assertThat(actualValueList)
|
||||
.asList()
|
||||
.hasSameElementsAs(expectedValueList);
|
||||
}
|
||||
|
||||
private JsonTestTypes getType(Object theValue) {
|
||||
if (theValue instanceof Map<?, ?>) {
|
||||
return JsonTestTypes.JSON_OBJECT;
|
||||
}
|
||||
|
||||
if (isJsonObjStr(theValue)) {
|
||||
getMap((String) theValue);
|
||||
return JsonTestTypes.JSON_OBJECT;
|
||||
}
|
||||
|
||||
if (isJsonList(theValue)) {
|
||||
return JsonTestTypes.JSON_LIST;
|
||||
}
|
||||
|
||||
return JsonTestTypes.STRING_NOT_JSON;
|
||||
}
|
||||
|
||||
private String getDifferentTypesMessage(String theKey, JsonTestTypes theActualValueType, JsonTestTypes theExpectedValueType) {
|
||||
return "Types mismatch. Te expected " + (theKey == null ? " " : "'" + theKey + "' ") +
|
||||
"value is a " + theExpectedValueType.myDisplay +
|
||||
" whereas the actual value is a " + theActualValueType.myDisplay;
|
||||
}
|
||||
|
||||
private boolean isJsonList(Object theValue) {
|
||||
return theValue instanceof Collection<?> ||
|
||||
(theValue instanceof String stringValue
|
||||
&& stringValue.trim().startsWith("[")
|
||||
&& stringValue.trim().endsWith("]"));
|
||||
}
|
||||
|
||||
private void assertJsonObject(Map<String, Object> theActualMap, String theKey, Object theValue) {
|
||||
Map<String, Object> expectedValueMap = getMap((String) theValue);
|
||||
Assertions.assertThat(expectedValueMap).isNotNull();
|
||||
|
||||
Assertions.assertThat(theActualMap.get(theKey)).isNotNull().isInstanceOf(Map.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> actualValueMap = (Map<String, Object>) theActualMap.get(theKey);
|
||||
|
||||
SoftAssertions lazyly = new SoftAssertions();
|
||||
for (String key : actualValueMap.keySet()) {
|
||||
lazyly.assertThat(actualValueMap)
|
||||
.as("Unexpected value for key: " + key + ":")
|
||||
.extracting(key).isEqualTo(expectedValueMap.get(key));
|
||||
}
|
||||
lazyly.assertAll();
|
||||
}
|
||||
|
||||
private boolean isJsonObjStr(Object theValue) {
|
||||
if (theValue instanceof String strValue) {
|
||||
String trimmed = trimAll(strValue);
|
||||
return trimmed.startsWith("{") && trimmed.endsWith("}") && isValidJson(trimmed);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String trimAll(String theString) {
|
||||
return theString.trim().replace("\n", "").replace("\t", "");
|
||||
}
|
||||
|
||||
private boolean isValidJson(String theStrValue) {
|
||||
getMap(theStrValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
public AssertJson hasKeysWithValues(List<String> theKeys, List<Object> theValues) {
|
||||
isNotNull();
|
||||
|
||||
checkSizes(theKeys.size(), theValues.size());
|
||||
|
||||
Map<String, Object> map = getMap(actual);
|
||||
|
||||
Assertions.assertThat(map).isNotNull();
|
||||
Assertions.assertThat(map.keySet()).containsAll(theKeys);
|
||||
checkKeysAndValues(map, theKeys, theValues);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void checkKeysAndValues(Map<String, Object> theExpected, List<String> theKeys, List<Object> theValues) {
|
||||
SoftAssertions lazyly = new SoftAssertions();
|
||||
for (int i = 0; i < theKeys.size(); i++) {
|
||||
lazyly.assertThat(theExpected)
|
||||
.as("Unexpected value for key: " + theKeys.get(i) + ":")
|
||||
.extracting(theKeys.get(i)).isEqualTo(theValues.get(i));
|
||||
}
|
||||
lazyly.assertAll();
|
||||
}
|
||||
|
||||
private boolean checkSizes(int keysSize, int valuesSize) {
|
||||
if (keysSize != valuesSize) {
|
||||
fail("Keys and values should have same size. Received " + keysSize + " keys and " + valuesSize + " values.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static Map<String, Object> getMap(String theJsonString) {
|
||||
try {
|
||||
return new ObjectMapper()
|
||||
.readValue(new ByteArrayInputStream(theJsonString.getBytes()), new TypeReference<>() {});
|
||||
|
||||
} catch (IOException theE) {
|
||||
fail("IOException: " + theE);
|
||||
}
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private List<?> getList(String theJsonString) {
|
||||
try {
|
||||
return new ObjectMapper()
|
||||
.readValue(new ByteArrayInputStream(theJsonString.getBytes()), new TypeReference<>() {});
|
||||
|
||||
} catch (IOException theE) {
|
||||
fail("IOException: " + theE);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
public AssertJson hasPaths(String... thePaths) {
|
||||
for (String path : thePaths) {
|
||||
hasPath(path);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssertJson hasPathWithValue(String thePath, String theValue) {
|
||||
String[] pathElements = thePath.split("\\.");
|
||||
if (pathElements.length == 1) {
|
||||
hasKeyWithValue(thePath, theValue);
|
||||
}
|
||||
|
||||
Map<String, Object> pathMap = getPathMap(thePath);
|
||||
String lastPathElement = pathElements[pathElements.length - 1];
|
||||
|
||||
if (isJsonObjStr(theValue)) {
|
||||
Assertions.assertThat(pathMap)
|
||||
.extracting(lastPathElement)
|
||||
.isEqualTo(getMap(theValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
if (isJsonList(theValue)) {
|
||||
Assertions.assertThat(pathMap)
|
||||
.extracting(lastPathElement)
|
||||
.asList()
|
||||
.hasSameElementsAs(getList(theValue));
|
||||
return this;
|
||||
}
|
||||
|
||||
// check last path element's value
|
||||
Assertions.assertThat(pathMap)
|
||||
.extracting(pathElements[pathElements.length-1])
|
||||
.isEqualTo(theValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssertJson hasPathsWithValues(List<String> thePaths, List<String> theValues) {
|
||||
if (thePaths.size() != theValues.size()) {
|
||||
fail("Paths size (" + thePaths.size() + ") is different than values size (" + theValues.size() + ")");
|
||||
return this;
|
||||
}
|
||||
|
||||
for (int i = 0; i < thePaths.size(); i++) {
|
||||
hasPathWithValue(thePaths.get(i), theValues.get(i));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private Map<String, Object> getPathMap(String thePath) {
|
||||
String[] pathElements = thePath.split("\\.");
|
||||
StringBuilder pathSoFar = new StringBuilder();
|
||||
|
||||
Map<String, Object> pathMap = getMap(actual);
|
||||
|
||||
for (int i = 0; i < pathElements.length-1; i++) {
|
||||
String pathElement = pathElements[i];
|
||||
pathSoFar.append(StringUtils.isNotEmpty(pathSoFar) ? "." + pathElement : pathElement);
|
||||
Object pathValue = pathMap.get(pathElement);
|
||||
|
||||
// all path values, other than the last, must be json objects (maps)
|
||||
assertIsJsonObject(pathSoFar.toString(), pathValue);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> aMap = (Map<String, Object>) pathValue;
|
||||
pathMap = aMap;
|
||||
}
|
||||
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
private void assertIsJsonObject(String thePath, Object theValue) {
|
||||
if (theValue instanceof Map<?, ?>) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (theValue instanceof String stringValue) {
|
||||
if (!isJsonObjStr(theValue)) {
|
||||
fail(thePath + " doesn't contain a json object but a plain string");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
getMap(stringValue);
|
||||
} catch (Exception theE) {
|
||||
fail(thePath + " doesn't contain a json object");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = "Path: " + thePath + "' is not a json object but a Json list";
|
||||
if (isJsonList(theValue)) {
|
||||
Assertions.assertThat(theValue)
|
||||
.as(msg)
|
||||
.isInstanceOf(Map.class);
|
||||
}
|
||||
}
|
||||
|
||||
enum JsonTestTypes {
|
||||
|
||||
STRING_NOT_JSON("plain string (not json)"),
|
||||
JSON_OBJECT("json object"),
|
||||
JSON_LIST("json list"),
|
||||
JSON_STRING("json string");
|
||||
|
||||
final String myDisplay;
|
||||
|
||||
JsonTestTypes(String theDisplay) {
|
||||
myDisplay = theDisplay;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,465 @@
|
|||
package ca.uhn.fhir.test.utilities;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.test.util.AssertJson.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class AssertJsonTest {
|
||||
|
||||
private final String myJsonString = """
|
||||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"age": 25,
|
||||
"address": {
|
||||
"streetAddress": "21 2nd Street",
|
||||
"city": "New York",
|
||||
"state": "NY",
|
||||
"postalCode": 10021
|
||||
},
|
||||
"phoneNumbers": [
|
||||
{
|
||||
"type": "home",
|
||||
"number": "212 555-1234"
|
||||
},
|
||||
{
|
||||
"type": "fax",
|
||||
"number": "646 555-4567"
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
String goodAddress = """
|
||||
{
|
||||
"streetAddress": "21 2nd Street",
|
||||
"city": "New York",
|
||||
"state": "NY",
|
||||
"postalCode": 10021
|
||||
}
|
||||
""";
|
||||
|
||||
String wrongAddress = """
|
||||
{
|
||||
"streetAddress": "432 Hillcrest Rd",
|
||||
"city": "Mississauga",
|
||||
"state": "ON",
|
||||
"postalCode": 10021
|
||||
}
|
||||
""";
|
||||
|
||||
String goodPhoneNumbers = """
|
||||
[
|
||||
{
|
||||
"type": "home",
|
||||
"number": "212 555-1234"
|
||||
},
|
||||
{
|
||||
"type": "fax",
|
||||
"number": "646 555-4567"
|
||||
}
|
||||
]
|
||||
""";
|
||||
|
||||
String wrongPhoneNumbers = """
|
||||
[
|
||||
{
|
||||
"type": "cell",
|
||||
"number": "212 555-9876"
|
||||
},
|
||||
{
|
||||
"type": "fax",
|
||||
"number": "646 666-4567"
|
||||
}
|
||||
]
|
||||
""";
|
||||
|
||||
@Test
|
||||
void testFluency() {
|
||||
assertThat(myJsonString)
|
||||
.hasPath("address.city")
|
||||
.hasPaths("firstName", "address.city")
|
||||
.hasKeys("firstName", "address")
|
||||
.hasExactlyKeys("firstName", "lastName", "age", "address", "phoneNumbers")
|
||||
.hasKeyWithValue("lastName", "Smith")
|
||||
.hasKeysWithValues(
|
||||
List.of("firstName", "lastName"),
|
||||
List.of("John", "Smith"))
|
||||
.hasExactlyKeysWithValues(
|
||||
List.of("firstName", "lastName", "age", "address", "phoneNumbers"),
|
||||
List.of("John", "Smith", 25, goodAddress, goodPhoneNumbers))
|
||||
.hasPath("lastName");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasPath {
|
||||
|
||||
@Test
|
||||
void test_success() {
|
||||
assertThat(myJsonString).hasPath("address.city");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_fails_pathNotFound() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPath("address.city.neighbourhood"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("address.city doesn't contain a json object but a plain string");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasPaths {
|
||||
|
||||
@Test
|
||||
void test_success() {
|
||||
assertThat(myJsonString).hasPaths("lastName", "address.city");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_fails_pathNotFound() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPaths("lastName", "address.city.neighbourhood"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("address.city doesn't contain a json object but a plain string");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasPathWithValue {
|
||||
|
||||
@Test
|
||||
void testStringValue_success() {
|
||||
assertThat(myJsonString).hasPathWithValue("address.city", "New York");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedStringValue_failure_isList() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue(
|
||||
"phoneNumbers.number",
|
||||
"212 555-1234"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Path: phoneNumbers' is not a json object but a Json list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedStringValue_failure_isObject() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue(
|
||||
"address",
|
||||
"432 Hillcrest Rd"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Types mismatch. Te expected 'address' value is a plain string (not json) whereas the actual value is a json object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedStringValue_failure_differentString() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue(
|
||||
"address.streetAddress",
|
||||
"181 Hillcrest Rd."))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("expected: \"181 Hillcrest Rd.\"")
|
||||
.hasMessageContaining("but was: \"21 2nd Street\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedObjectValue_success() {
|
||||
assertThat(myJsonString).hasPathWithValue("address", goodAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedObjectValue_failure_isString() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("age", goodAddress))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Types mismatch. Te expected 'age' value is a json object whereas the actual value is a plain string (not json)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedObjectValue_failure_isList() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("phoneNumbers", "223-217-5555"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Types mismatch. Te expected 'phoneNumbers' value is a plain string (not json) whereas the actual value is a json list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedObjectValue_failure_different() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("address", wrongAddress))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
Multiple Failures (3 failures)
|
||||
-- failure 1 --
|
||||
[Unexpected value for key: streetAddress:]\s
|
||||
expected: "432 Hillcrest Rd"
|
||||
but was: "21 2nd Street"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 2 --
|
||||
[Unexpected value for key: city:]\s
|
||||
expected: "Mississauga"
|
||||
but was: "New York"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 3 --
|
||||
[Unexpected value for key: state:]\s
|
||||
expected: "ON"
|
||||
but was: "NY"
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedListValue_success() {
|
||||
assertThat(myJsonString).hasPathWithValue("phoneNumbers", goodPhoneNumbers);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedListValue_failure_isString() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("phoneNumbers", "222-555-7654"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Types mismatch. Te expected 'phoneNumbers' value is a plain string (not json) whereas the actual value is a json list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedListValue_failure_isObject() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("phoneNumbers", goodAddress))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Types mismatch. Te expected 'phoneNumbers' value is a json object whereas the actual value is a json list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExpectedListValue_failure_different() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathWithValue("phoneNumbers", wrongPhoneNumbers))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("Expecting ArrayList:")
|
||||
.hasMessageContaining("""
|
||||
element(s) not found:
|
||||
[{"number"="212 555-9876", "type"="cell"},
|
||||
{"number"="646 666-4567", "type"="fax"}]
|
||||
and element(s) not expected:
|
||||
[{"number"="212 555-1234", "type"="home"},
|
||||
{"number"="646 555-4567", "type"="fax"}]
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasPathsWithValues {
|
||||
|
||||
@Test
|
||||
void testMixedValues_success() {
|
||||
assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(goodPhoneNumbers, goodAddress, "Smith"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDifferentSizes_failure() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers"), List.of(goodPhoneNumbers, wrongPhoneNumbers)))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageStartingWith("Paths size (1) is different than values size (2)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_wrongTypeString() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(goodPhoneNumbers, goodAddress, wrongAddress)))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessage("Types mismatch. Te expected 'lastName' value is a json object whereas the actual value is a plain string (not json)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_wrongTypeList() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of("Wesson", goodAddress, "Smith")))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessage("Types mismatch. Te expected 'phoneNumbers' value is a plain string (not json) whereas the actual value is a json list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_wrongTypeObject() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(goodPhoneNumbers, "Wesson", "Smith")))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessage("Types mismatch. Te expected 'address' value is a plain string (not json) whereas the actual value is a json object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_differentString() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(goodPhoneNumbers, goodAddress, "Wesson")))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("[Extracted: lastName]")
|
||||
.hasMessageContaining("expected: \"Wesson\"")
|
||||
.hasMessageContaining("but was: \"Smith\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_differentList() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(wrongPhoneNumbers, goodAddress, "Smith")))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
element(s) not found:
|
||||
[{"number"="212 555-9876", "type"="cell"},
|
||||
{"number"="646 666-4567", "type"="fax"}]
|
||||
and element(s) not expected:
|
||||
[{"number"="212 555-1234", "type"="home"},
|
||||
{"number"="646 555-4567", "type"="fax"}]
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMixedValues_failure_differentObject() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasPathsWithValues(List.of("phoneNumbers", "address", "lastName"),
|
||||
List.of(goodPhoneNumbers, wrongAddress, "Smith")))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
Multiple Failures (3 failures)
|
||||
-- failure 1 --
|
||||
[Unexpected value for key: streetAddress:]\s
|
||||
expected: "432 Hillcrest Rd"
|
||||
but was: "21 2nd Street"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 2 --
|
||||
[Unexpected value for key: city:]\s
|
||||
expected: "Mississauga"
|
||||
but was: "New York"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 3 --
|
||||
[Unexpected value for key: state:]\s
|
||||
expected: "ON"
|
||||
but was: "NY"
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
void hasExactlyKeys() {
|
||||
assertThat(myJsonString).hasExactlyKeys("firstName", "lastName", "age", "address", "phoneNumbers");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasExactlyKeys {
|
||||
|
||||
@Test
|
||||
void hasExactlyKeys_succeeds() {
|
||||
assertThat(myJsonString).hasExactlyKeys("firstName", "lastName", "age", "address", "phoneNumbers");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasExactlyKeys_fails() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString)
|
||||
.hasExactlyKeys("firstName", "age", "address", "phoneNumbers", "extraKey"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
element(s) not found:
|
||||
["extraKey"]""")
|
||||
.hasMessageContaining("""
|
||||
and element(s) not expected:
|
||||
["lastName"]""");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasKeysWithValues {
|
||||
|
||||
@Test
|
||||
void hasExactlyKeysWithValues_succeeds() {
|
||||
assertThat(myJsonString).hasKeysWithValues(
|
||||
List.of("firstName", "lastName", "age"),
|
||||
List.of("John", "Smith", 25));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testKeysAndValues_haveDifferentSizes_fails() {
|
||||
assertThatThrownBy(() ->
|
||||
assertThat(myJsonString).hasKeysWithValues(
|
||||
List.of("firstName", "lastName", "age"),
|
||||
List.of("John", "Wesson", 31, 28)))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessage("Keys and values should have same size. Received 3 keys and 4 values.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testKeysAndValues_haveDifferentValues_failsShowingAllProblems() {
|
||||
assertThatThrownBy(() ->
|
||||
assertThat(myJsonString).hasKeysWithValues(
|
||||
List.of("firstName", "lastName", "age"),
|
||||
List.of("John", "Wesson", 31)))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
Multiple Failures (2 failures)
|
||||
-- failure 1 --
|
||||
[Unexpected value for key: lastName:]\s
|
||||
expected: "Wesson"
|
||||
but was: "Smith"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 2 --
|
||||
[Unexpected value for key: age:]\s
|
||||
expected: 31
|
||||
but was: 25
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasKeys {
|
||||
@Test
|
||||
void testSuccess() {
|
||||
assertThat(myJsonString).hasKeys("address", "phoneNumbers");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasKeys("address", "weight"))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
but could not find the following element(s):
|
||||
["weight"]
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class TestHasKeyWithValue {
|
||||
|
||||
@Test
|
||||
void testSuccess() {
|
||||
assertThat(myJsonString).hasKeyWithValue("address", goodAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure() {
|
||||
assertThatThrownBy(() -> assertThat(myJsonString).hasKeyWithValue("address", wrongAddress))
|
||||
.isInstanceOf(AssertionError.class)
|
||||
.hasMessageContaining("""
|
||||
Multiple Failures (3 failures)
|
||||
-- failure 1 --
|
||||
[Unexpected value for key: streetAddress:]\s
|
||||
expected: "432 Hillcrest Rd"
|
||||
but was: "21 2nd Street"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 2 --
|
||||
[Unexpected value for key: city:]\s
|
||||
expected: "Mississauga"
|
||||
but was: "New York"
|
||||
""")
|
||||
.hasMessageContaining("""
|
||||
-- failure 3 --
|
||||
[Unexpected value for key: state:]\s
|
||||
expected: "ON"
|
||||
but was: "NY"
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue