在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:lukas-krecan/JsonUnit开源软件地址:https://github.com/lukas-krecan/JsonUnit开源编程语言:Java 97.6%开源软件介绍:JsonUnitJsonUnit is a library that simplifies JSON comparison in tests. APIsThere are several different APIs you can use. They all have more or less the same features, just the usage is slightly different. AssertJ integrationThis is brand new API which combines power of JsonUnit and AssertJ. If you are not sure, which API to use, pick this one. import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;
...
// compares two JSON documents (note lenient parsing of expected value)
assertThatJson("{\"a\":1, \"b\":2}").isEqualTo("{b:2, a:1}");
// objects are automatically serialized before comparison
assertThatJson(jsonObject).isEqualTo("{\n\"test\": 1\n}");
// AssertJ map assertions (numbers are converted to BigDecimals)
assertThatJson("{\"a\":1}").isObject().containsEntry("a", BigDecimal.valueOf(1));
// Type placeholders
assertThatJson("{\"a\":1, \"b\": {\"c\" :3}}")
.isObject().containsValue(json("{\"c\" :\"${json-unit.any-number}\"}"));
// AssertJ string assertion
assertThatJson("{\"a\": \"value\"")
.node("a").isString().isEqualTo("value");
// AssertJ array assertion
assertThatJson("{\"a\":[{\"b\": 1}, {\"c\": 1}, {\"d\": 1}]}")
.node("a").isArray().contains(json("{\"c\": 1}"));
// Can ignore array order
assertThatJson("{\"a\":[{\"b\": 1}, {\"c\": 1}, {\"d\": 1}]}")
.when(Option.IGNORING_ARRAY_ORDER).node("a").isArray()
.isEqualTo(json("[{\"c\": 1}, {\"b\": 1} ,{\"d\": 1}]"));
// custom matcher
assertThatJson("{\"test\":-1}")
.withConfiguration(c -> c.withMatcher("positive", greaterThan(valueOf(0))))
.isEqualTo("{\"test\": \"${json-unit.matches:positive}\"}");
// and
assertThatJson("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}").and(
a -> a.node("test.a").isEqualTo(1),
a -> a.node("test.b").isEqualTo(2)
);
// JsonPath support
assertThatJson(json)
.inPath("$.store.book")
.isArray()
.contains(json(
" {\n" +
" \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.96\n" +
" }"
)); JsonUnit tries to be clever when parsing the expected value. If the value can be parsed as valid JSON, it's parsed so. If it can't be parsed, it's considered to be just a string to be compared. It usually works, but it can lead to unexpected situations, usually with primitive values like numbers and booleans. // This test does NOT pass. "1" is parsed as JSON containing number 1, actual value is a string.
assertThatJson("{\"id\":\"1\", \"children\":[{\"parentId\":\"1\"}]}")
.inPath("children[*].parentId")
.isArray()
.containsOnly("1");
// You have to wrap the expected value by `JsonAssertions.value()`
// to prevent parsing
assertThatJson("{\"id\":\"1\", \"children\":[{\"parentId\":\"1\"}]}")
.inPath("children[*].parentId")
.isArray()
.containsOnly(value("1"));
// "true" is valid JSON so it gets parsed to primitive `true`
// Have to wrap it to JsonAssertions.value() in order to make sure it's not parsed
assertThatJson("{\"root\":[\"true\"]}").node("root").isArray().containsExactly(value("true")); On the other hand, if you want to make sure that the expected value is parsed as JSON, use Kotlin supportFollowing Kotlin API is supported (notice different import) // Kotlin
import net.javacrumbs.jsonunit.assertj.assertThatJson
assertThatJson("""{"root":{"a":1, "b": 2}}""") {
isObject
node("root.a").isEqualTo(1)
node("root.b").isEqualTo(2)
} To use AssertJ integration, import <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-assertj</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> For more examples see the tests. Hamcrests matchersYou use Hamcrest matchers in the following way import static net.javacrumbs.jsonunit.JsonMatchers.*;
import static org.junit.Assert.*;
import static net.javacrumbs.jsonunit.core.util.ResourceUtils.resource;
...
assertThat("{\"test\":1}", jsonEquals("{\"test\": 1}"));
assertThat("{\"test\":1}", jsonPartEquals("test", 1));
assertThat("{\"test\":[1, 2, 3]}", jsonPartEquals("test[0]", 1));
assertThat("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}",
jsonEquals("{\"test\":{\"b\":2}}").when(IGNORING_EXTRA_FIELDS));
// Can use other Hamcrest matchers too
assertThat("{\"test\":1}", jsonPartMatches("test", is(valueOf(1))))
assertThat("{\"test\":1}", jsonEquals(resource("test.json"))); To use import <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> For more examples see the tests. Spring MVC assertionsJsonUnit supports Spring MVC test assertions. For example import static net.javacrumbs.jsonunit.spring.JsonUnitResultMatchers.json;
...
mockMvc.perform(get("/sample").andExpect(
json().isEqualTo("{\"result\":{\"string\":\"stringValue\", \"array\":[1, 2, 3],\"decimal\":1.00001}}")
);
mockMvc.perform(get("/sample").andExpect(
json().node("result.string2").isAbsent()
);
mockMvc.perform(get("/sample").andExpect(
json().node("result.array").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})
);
mockMvc.perform(get("/sample").andExpect(
json().node("result.array").matches(everyItem(lessThanOrEqualTo(valueOf(4))))
); Following Kotlin DSL is supported: mockMvc.get(path).andExpect {
jsonContent {
node("root").isEqualTo(CORRECT_JSON)
}
} Inside To use import <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-spring</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> For more examples see the tests. Spring WebTestClientTo integrate with Spring WebTest client do import static net.javacrumbs.jsonunit.spring.WebTestClientJsonMatcher.json;
...
client.get().uri(path).exchange().expectBody().consumeWith(
json().isEqualTo("{\"result\":{\"string\":\"stringValue\", \"array\":[1, 2, 3],\"decimal\":1.00001}}")
);
client.get().uri(path).exchange().expectBody().consumeWith(
json().node("result.string2").isAbsent()
);
client.get().uri(path).exchange().expectBody().consumeWith(
json().node("result.array").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})
);
client.get().uri(path).exchange().expectBody().consumeWith(
json().node("result.array").matches(everyItem(lessThanOrEqualTo(valueOf(4))))
); For Kotlin, you can use our bespoke DSL import net.javacrumbs.jsonunit.spring.jsonContent
...
client.get().uri(path).exchange().expectBody()
.jsonContent {
isEqualTo(CORRECT_JSON)
} Import <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-spring</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> For more examples see the tests. Spring REST client assertionsimport static net.javacrumbs.jsonunit.spring.JsonUnitRequestMatchers.json;
...
mockServer.expect(requestTo(URI))
.andExpect(json().isEqualTo(json))
.andRespond(withSuccess(jsonResponse, MediaType.APPLICATION_JSON_UTF8)); To use import <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-spring</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> For more examples see the tests. Vintage APIsThere are two API types that are still supported but not recommnded to use for new tests - Fluent assertions and Standard assert. They are documented here FeaturesJsonUnit support all this features regardless of API you use. JsonPath supportYou can use JsonPath navigation together with JsonUnit. It has native support in AssertJ integration so you can do something like this: // AssertJ style
assertThatJson(json)
.inPath("$.store.book")
.isArray()
.contains(json(
" {\n" +
" \"category\": \"reference\",\n" +
" \"author\": \"Nigel Rees\",\n" +
" \"title\": \"Sayings of the Century\",\n" +
" \"price\": 8.96\n" +
" }"
)); For other API styles you have to first import JsonPath support module <dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-json-path</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency> and then use instead of actual value import static net.javacrumbs.jsonunit.jsonpath.JsonPathAdapter.inPath;
...
// Fluent assertions
assertThatJson(inPath(json, "$.store.book[*].author"))
.when(Option.IGNORING_ARRAY_ORDER)
.isEqualTo("['J. R. R. Tolkien', 'Nigel Rees', 'Evelyn Waugh', 'Herman Melville']"); Ignoring valuesSometimes you need to ignore certain values when comparing. It is possible to use // AssertJ API
assertThatJson("{\"a\":1}")
.isEqualTo(json("{\"a\":\"${json-unit.ignore}\"}")); Please note that the assertion will fail if the Ignoring elementsIf the element needs to be ignored completely you can use // AssertJ API
assertThatJson("{\"root\":{\"test\":1, \"ignored\": null}}")
.isEqualTo("{\"root\":{\"test\":1, \"ignored\": \"${json-unit.ignore-element}\"}}"); The assertion will not fail if the element is missing in the actual value. Ignoring paths
// AssertJ style
assertThatJson("{\"root\":{\"test\":1, \"ignored\": 1}}")
.whenIgnoringPaths("root.ignored"))
.isEqualTo("{\"root\":{\"test\":1}}");
// Hamcrest matcher
assertThat(
"{\"root\":{\"test\":1, \"ignored\": 2}}",
jsonEquals("{\"root\":{\"test\":1, \"ignored\": 1}}").whenIgnoringPaths("root.ignored")
); Array index placeholder assertThatJson("[{\"a\":1, \"b\":2},{\"a\":1, \"b\":3}]")
.whenIgnoringPaths("[*].b")
.isEqualTo("[{\"a\":1, \"b\":0},{\"a\":1, \"b\":0}]"); Please note that if you use JsonPath, you should start the path to be ignored by JsonPath with whenIgnoringPaths example: // AssertJ API
assertThatJson("{\"fields\":[" +
"{\"key\":1, \"name\":\"AA\"}," +
"{\"key\":2, \"name\":\"AB\"}," +
"{\"key\":3, \"name\":\"AC\"}" +
"]}")
.whenIgnoringPaths("$.fields[?(@.name=='AA')].key")
.isEqualTo("{\"fields\":[" +
"{\"key\":2, \"name\":\"AA\"}," +
"{\"key\":2, \"name\":\"AB\"}," +
"{\"key\":3, \"name\":\"AC\"}" +
"]}"); Regular expressionsIt is also possible to use regular expressions to compare string values assertThatJson("{\"test\": \"ABCD\"}")
.isEqualTo("{\"test\": \"${json-unit.regex}[A-Z]+\"}"); For matching just part of the string, you can use this (we have to escape twice, one for Java, once for JSON) assertThatJson("{\"test\": \"This is some text followed by: ABCD, followed by this\"}")
.isEqualTo("{\"test\": \"${json-unit.regex}^\\\\QThis is some text followed by: \\\\E[A-Z]+\\\\Q, followed by this\\\\E$\"}"); Since this is quite hard to write, you can implement an expression builder like this. Type placeholdersIf you want to assert just a type, but you do not care about the exact value, you can use any-* placeholder like this assertThatJson("{\"test\":\"value\"}")
.isEqualTo("{test:'${json-unit.any-string}'}");
assertThatJson("{\"test\":true}")
.isEqualTo("{\"test\":\"${json-unit.any-boolean}\"}");
assertThatJson("{\"test\":1.1}")
.isEqualTo("{\"test\":\"${json-unit.any-number}\"}"); You can also use hash instead of string Custom matchersIn some special cases you might want to use your own matcher in the expected document. assertThatJson("{\"test\":-1}")
.withMatcher("positive", greaterThan(valueOf(0)))
.isEqualTo("{\"test\": \"${json-unit.matches:positive}\"}"); In even more special cases, you might want to parametrize your matcher. Matcher<?> divisionMatcher = new DivisionMatcher();
assertThatJson("{\"test\":5}")
.withMatcher("isDivisibleBy", divisionMatcher)
.isEqualTo("{\"test\": \"${json-unit.matches:isDivisibleBy}3\"}");
private static class DivisionMatcher extends BaseMatcher<Object> implements ParametrizedMatcher {
private BigDecimal param;
public boolean matches(Object item) {
return ((BigDecimal)item).remainder(param).compareTo(ZERO) == 0;
}
public void describeTo(Description description) {
description.appendValue(param);
}
@Override
public void describeMismatch(Object item, Description description) {
description.appendText("It is not divisible by ").appendValue(param);
}
public void setParameter(String parameter) {
this.param = new BigDecimal(parameter);
}
} If you need a matcher with more than one parameter, you can implement it like this. OptionsThere are multiple options how you can configure the comparison TREATING_NULL_AS_ABSENT - fields with null values are equivalent to absent fields. For example, this test passes assertThatJson("{\"test\":{\"a\":1, \"b\": null}}")
.when(TREATING_NULL_AS_ABSENT)
.isEqualTo("{\"test\":{\"a\":1}}"); IGNORING_ARRAY_ORDER - ignores order in arrays assertThatJson("{\"test\":[1,2,3]}")
.when(IGNORING_ARRAY_ORDER)
.isEqualTo("{\"test\":[3,2,1]}"); IGNORING_EXTRA_ARRAY_ITEMS - ignores unexpected array items 全部评论
专题导读
上一篇:canonical/microk8s: MicroK8s is a small, fast, single-package Kubernetes for dev ...发布时间:2022-07-09下一篇:ant0ine/go-json-rest: A quick and easy way to setup a RESTful JSON API发布时间:2022-07-08热门推荐
热门话题
阅读排行榜
|
请发表评论