revinate / assertj-json Goto Github PK
View Code? Open in Web Editor NEWA set of AssertJ assertions to validate JSON.
License: MIT License
A set of AssertJ assertions to validate JSON.
License: MIT License
Sometimes it is useful to validate when a jsonpath expression does not return anything, i.e.: validate if your serialized is ignoring entries with null value properly. The jsonpath library throws an exception when the path cannot evaluated, in this case the assertion utility can just wrap this exception and validate the path does not exist.
After updating to assertj-core 3.11.1 I've started seeing:
java.lang.NoSuchMethodError: org.assertj.core.api.Assertions.assertThat(Ljava/lang/String;)Lorg/assertj/core/api/AbstractCharSequenceAssert;
at com.revinate.assertj.json.JsonPathAssert.jsonPathAsString(JsonPathAssert.java:32)
when running my tests.
This seems to have been caused by a signature changes in the fix for assertj/assertj#1269, in particular the change to Assertions.java:
- public static AbstractCharSequenceAssert<?, String> assertThat(String actual) {
+ public static AbstractStringAssert<?> assertThat(String actual) {
I think it's sufficient to just bump the assertj-core dependency to 3.11.1 to fix this, though probably jsonPathAsString
should return an AbstractStringAssert<?>
rather than AbstractCharSequenceAssert<?, String>
to pick up the additional methods that were added in that assertj-core change.
it would be very convenient to accept string along with DocumentContext, and do the parsing under the hood.
In most cases that saves some space that is pretty important in tests, as there a lot of assertions.
If there is this JSON:
{
"admin" : false,
"user" : true,
"address" : null
}
I would like to have following assertions:
DocumentContext ctx = JsonPath.parse("{\n" +
" \"admin\" : false,\n" +
" \"user\" : true,\n" +
" \"address\" : null\n" +
"}");
assertThat(ctx).jsonPathAsBoolean("admin").isFalse();
assertThat(ctx).jsonPathAsBoolean("user").isTrue();
assertThat(ctx).jsonPath("address").isNull();
assertThat(ctx2).jsonPath("user").isNotNull();
This would be nice feature.
And here is the implementation:
public AbstractBooleanAssert<?> jsonPathAsBoolean(String path) {
return Assertions.assertThat(actual.read(path, Boolean.class));
}
public AbstractObjectAssert<?, Object> jsonPath(String path) {
return Assertions.assertThat(actual.read(path, Object.class));
}
ClassPath:
com.revinate:assertj-json:1.0.1
com.jayway.jsonpath:json-path:2.0.0
com.google.code.gson:gson:2.7
Code to reproduce:
String json = "{"id":186,"areaIds":[39]}";
Configuration config = Configuration.builder()
.jsonProvider(new GsonJsonProvider())
.mappingProvider(new GsonMappingProvider())
.build();
DocumentContext response = JsonPath.using(config).parse(content);
JsonPathAssert.assertThat(response)
.jsonPathAsListOf("$.areaIds", Integer.class)
.containsExactly(39);
java.lang.AssertionError:
Expecting:
<[39.0]>
to contain exactly (and in same order):
<[39]>
but some elements were not found:
<[39]>
and others were not expected:
<[39.0]>
After a quick investigation:
com.jayway.jsonpath.spi.mapper.GsonMappingProvider
@OverRide
public T map(Object source, TypeRef targetType, Configuration configuration) { // source "[47]"
try {
return (T) factory.call().getAdapter(TypeToken.get(targetType.getType())).fromJsonTree((JsonElement) source); // result "[47.0]"
} catch (Exception e){
throw new MappingException(e);
}
}
com.google.gson.internal.bind,ObjectTypeAdapter
JsonToken token is a NUMBER and ObjectTypeAdapter will always return Double.
case NUMBER: // * A JSON number represented in this API by a Java {@code double}, {@code long}, or {@code int}.
return in.nextDouble();
Doing assertion like this:
JsonPathAssert(ctx).jsonPathAsString("$.entities").isEmpty();
And got following exception:
java.lang.RuntimeException: Invalid or non Implemented status createArray() in class net.minidev.json.writer.BeansMapper$Bean
at net.minidev.json.writer.JsonReaderI.createArray(JsonReaderI.java:98)
at net.minidev.json.parser.JSONParserBase.readArray(JSONParserBase.java:235)
at net.minidev.json.parser.JSONParserBase.readFirst(JSONParserBase.java:300)
at net.minidev.json.parser.JSONParserBase.parse(JSONParserBase.java:154)
at net.minidev.json.parser.JSONParserString.parse(JSONParserString.java:58)
at net.minidev.json.parser.JSONParser.parse(JSONParser.java:263)
at net.minidev.json.JSONValue.parse(JSONValue.java:206)
at com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider.map(JsonSmartMappingProvider.java:82)
at com.jayway.jsonpath.internal.JsonContext.convert(JsonContext.java:192)
at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:158)
at com.revinate.assertj.json.JsonPathAssert.jsonPathAsString(JsonPathAssert.java:31)
Could you say what is the reason and how to fix it?
Assert field by field is annoying and sometimes we want to compare the whole result.
Something like
val request = ChargeRequest(listOf(ItemRequest(1, "test", 1)), MetadataRequest("0001", ""))
val exectedJson = """
{"metadataRequest":{"custom_id":"0001", "notification_url":""},"items":[{"amount":1,"name":"test","value":1}]}
""".trimIndent()
JSONAssert.assertEquals(request.toJsonString, exectedJson, true)
In JSONAssert, there is the strict configuration. When true all fields must be equal and have the same property count. When false the fields that exist on the expectations must match, but extra fields are allowed.
For example:
object a:
{
"foo": "bar",
"bar": "foo"
}
object b:
{
"foo": "bar"
}
In strict mode: a != b
Strict mode false: a = b
The build on travis-ci
is failing with the following error:
$ openssl aes-256-cbc -pass pass:$SONATYPE_PASS -in deploy/secring.gpg.enc -out deploy/secring.gpg -d
bad decrypt
140340207703712:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:539:
Currently I am using AssertJ library for http response assertion, and also needed to assert json in the same tests.
Currently I need to specify namespace for assertThat method, because there is a conflict in names.
com.revinate.assertj.json.JsonPathAssert.assertThat;
and
org.assertj.core.api.assertThat;
Not sure what did you do this, but because of this it is completely inconvenient to write tests using both libraries.
Why not assertThatJson().method?
Is it possible to provide fix for this situation?
With the new version of assertJ like 3.6.2 I get the following error:
java.lang.NoSuchMethodError: org.assertj.core.api.Assertions.assertThat(Ljava/util/List;)Lorg/assertj/core/api/AbstractListAssert; at com.revinate.assertj.json.JsonPathAssert.jsonPathAsListOf(JsonPathAssert.java:54)
We should let the users choose other JSON providers if possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.