Giter Club home page Giter Club logo

jsonunit's Introduction

JsonUnit Build Status Maven Central

JsonUnit is a library that simplifies JSON comparison in unit tests. It's strongly inspired by XmlUnit. The usage is simple:

import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;

...

// compares two JSON documents
assertJsonEquals("{\"test\":1}", "{\n\"foo\": 1\n}");

// compares only part
assertJsonPartEquals("2", "{\"test\":[{\"value\":1},{\"value\":2}]}",
             "test[1].value");

// extra options can be specified
assertJsonEquals("{\"test\":{\"a\":1}}",
		     "{\"test\":{\"a\":1, \"b\": null}}",
    	     when(TREATING_NULL_AS_ABSENT));

// compares only the structure, not the values
assertJsonStructureEquals("[{\"test\":1}, {\"test\":2}]", 
			      "[{\n\"test\": 1\n}, {\"TEST\": 4}]")

When the values are compared, order of elements and whitespaces are ignored.

Hamcrests matchers

You use Hamcrest matchers in the following way

import static net.javacrumbs.jsonunit.JsonMatchers.*;
import static org.junit.Assert.*;
...

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))))

Fluent assertions

Fluent (FEST or AssertJ like) assertions are supported by a special module json-unit-fluent

import static net.javacrumbs.jsonunit.fluent.JsonFluentAssert.assertThatJson;
...

// compares entire documents
assertThatJson("{\"test\":1}").isEqualTo("{\"test\":2}");

// compares only parts of the document
assertThatJson("{\"test1\":2, \"test2\":1}")
    .node("test1").isEqualTo(2)
    .node("test2").isEqualTo(2);

assertThatJson("{\"root\":{\"test\":[1,2,3}}")
    .node("root.test[0]").isEqualTo(1);

// compares only the structure
assertThatJson("{\"test\":1}").hasSameStructureAs("{\"test\":21}");

// ignores a value
assertThatJson("{\"test\":1}").isEqualTo("{\"test\":\"${json-unit.ignore}\"}");

// ignores extra fields
assertThatJson("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}")
	.when(IGNORING_EXTRA_FIELDS).isEqualTo("{\"test\":{\"b\":2}}");
	
// array length comparison
assertThatJson("{\"test\":[1,2,3]}").node("test")
	.isArray().ofLength(2);

// using Hamcrest matcher
assertThatJson("{\"test\":\"one\"}").node("test")
    .matches(equalTo("one"));

// Numbers sent to matchers are BigDecimals.
import static java.math.BigDecimal.valueOf;
...
assertThatJson("{\"test\":[{\"value\":1},{\"value\":2},{\"value\":3}]}")
    .node("test")
    .matches(everyItem(jsonPartMatches("value", lessThanOrEqualTo(valueOf(4)))));

Hamcrest matchers in fluent assertions

It is possible to combine fluent assertions with hamcrest matchers using matches method. For example

 assertThatJson("{\"test\":[1,2,3]}").node("test").matches(hasItem(valueOf(1)));

 assertThatJson("{\"test\":[{\"value\":1},{\"value\":2},{\"value\":3}]}")
    .node("test")
    .matches(everyItem(jsonPartMatches("value", lessThanOrEqualTo(valueOf(4)))));

Spring MVC assertions

Since version 1.7.0 JsonUnit supports Spring MVC test assertions. For example

import static net.javacrumbs.jsonunit.spring.JsonUnitResultMatchers.json;
...

this.mockMvc.perform(get("/sample").andExpect(
    json().isEqualTo("{\"result\":{\"string\":\"stringValue\", \"array\":[1, 2, 3],\"decimal\":1.00001}}")
);
this.mockMvc.perform(get("/sample").andExpect(
    json().node("result.string2").isAbsent()
);
this.mockMvc.perform(get("/sample").andExpect(
    json().node("result.array").when(Option.IGNORING_ARRAY_ORDER).isEqualTo(new int[]{3, 2, 1})
);
this.mockMvc.perform(get("/sample").andExpect(
    json().node("result.array").matches(everyItem(lessThanOrEqualTo(valueOf(4))))
);

Ignoring values

Sometimes you need to ignore certain values when comparing. It is possible to use ${json-unit.ignore} placeholder like this

assertJsonEquals("{\"test\":\"${json-unit.ignore}\"}",
    "{\n\"test\": {\"object\" : {\"another\" : 1}}}");

Options

There 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

assertJsonEquals("{\"test\":{\"a\":1}}",
                 "{\"test\":{\"a\":1, \"b\": null, \"c\": null}}",
                 when(TREATING_NULL_AS_ABSENT));

IGNORING_ARRAY_ORDER - ignores order in arrays

assertJsonEquals("{\"test\":[1,2,3]}", 
                 "{\"test\":[3,2,1]}",
                 when(IGNORING_ARRAY_ORDER));

IGNORING_EXTRA_FIELDS - ignores extra fileds in the compared value

assertJsonEquals("{\"test\":{\"b\":2}}", 
                 "{\"test\":{\"a\":1, \"b\":2, \"c\":3}}",
                 when(IGNORING_EXTRA_FIELDS));

IGNORE_VALUES - ignores values and compares only types

assertJsonEquals("{\"test\":{\"a\":1,\"b\":2,\"c\":3}}", 
                 "{\"test\":{\"a\":3,\"b\":2,\"c\":1}}",
                 when(IGNORING_VALUES));

It is possible to combine options.

assertJsonEquals("{\"test\":[{\"key\":1},{\"key\":2},{\"key\":3}]}", 
                 "{\"test\":[{\"key\":3},{\"key\":2, \"extraField\":2},{\"key\":1}]}",
                 when(IGNORING_ARRAY_ORDER, IGNORING_EXTRA_FIELDS));

In Hamcrest assertion you can set the option like this

assertThat("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}",
           jsonEquals("{\"test\":{\"b\":2}}").when(IGNORING_EXTRA_FIELDS));

For standard asserts and Hamcrest matchers, it is possible to set the configuration globally

JsonAssert.setOptions(IGNORING_ARRAY_ORDER, IGNORING_EXTRA_FIELDS);

In fluent assertion, you can set options in the following way

assertThatJson("{\"test\":{\"a\":1, \"b\":2, \"c\":3}}")
    .when(IGNORING_EXTRA_FIELDS).isEqualTo("{\"test\":{\"b\":2}}");

Please note that when method has to be called before the actual comparison.

Numeric comparison

Numbers are by default compared in the following way:

  • If the type differs, the number is different. So 1 and 1.0 are different (int vs. float)
  • Floating number comparison is exact

You can change this behavior by setting tolerance

assertJsonEquals("1", "\n1.009\n", withTolerance(0.01));

or globally

JsonAssert.setTolerance(0.01);

or for fluent assertions

assertThatJson("{\"test\":1.00001}").node("test").withTolerance(0.001).isEqualTo(1);

Or you can use Hamcrest matcher

import static java.math.BigDecimal.valueOf;
...
assertThatJson("{\"test\":1.10001}").node("test")
        .matches(closeTo(valueOf(1.1), valueOf(0.001)));

Logging

Although the differences are printed out by the assert statement, sometimes you use JsonUnit with other libraries like Jadler that do not print the differences between documents. In such case, you can switch on the logging. JsonUnit uses SLF4J. The only thing you need to do is to configure your logging framework to log net.javacrumbs.jsonunit.difference on DEBUG level.

Maven dependency

JsonUnit is accessible in Maven central repository. In order for it to work, you need either, Jackson 1.x or Jackson 2.x or Gson on the classpath. Since 1.5.0 there is only one version for both versions of Jackson

<dependency>
	<groupId>net.javacrumbs.json-unit</groupId>
	<artifactId>json-unit</artifactId>
    <version>1.7.0</version>
	<scope>test</scope>
</dependency>

To use fluent assertions:

<dependency>
	<groupId>net.javacrumbs.json-unit</groupId>
	<artifactId>json-unit-fluent</artifactId>
    <version>1.7.0</version>
	<scope>test</scope>
</dependency>

To use Spring MVC assertions:

<dependency>
	<groupId>net.javacrumbs.json-unit</groupId>
	<artifactId>json-unit-spring</artifactId>
    <version>1.7.0</version>
	<scope>test</scope>
</dependency>

Licence

JsonUnit is licensed under Apache 2.0 licence.

jsonunit's People

Contributors

amergey avatar andrewscode avatar frelar avatar joeltucci avatar liry avatar lukas-krecan avatar lukas-krecan-gdc avatar nopolabs avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.