Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate complex JSONObjects in a JUnit test?

How can I properly validate fields of a JSONObject in a JUnit @Test?

{
    "persons": [
        "adults": [
            {
                "name": ".."
                "age": ..
            },
            {
                "name": ".."
                "age": ..
            }
        ]
    ]
}

I mean, if testing on a spring-managed webservice, I could use jsonPath() similar as follows:

mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
    .andExpect(jsonPath("$.persons[0].adults[0].name", is("John")));

But I'm not using a webservice here, but want to validate just a json object.

Could I anyhow make somehow usw of the jsonPath() method of spring, or are there similar techniques?

like image 510
membersound Avatar asked Feb 07 '18 17:02

membersound


2 Answers

You could use Jayway JsonPath without its Spring wrapping.

For example:

String json = "{\n" +
        "  \"persons\": [\n" +
        "    {\n" +
        "      \"adults\": [\n" +
        "        {\n" +
        "          \"name\": \"John\",\n" +
        "          \"age\": 25\n" +
        "        },\n" +
        "        {\n" +
        "          \"name\": \"Jill\",\n" +
        "          \"age\": 36\n" +
        "        }\n" +
        "      ]\n" +
        "    }\n" +
        "  ]\n" +
        "}";

DocumentContext documentContext = JsonPath.parse(json);

assertThat(documentContext.read("$.persons[0].adults[0].name"), is("John"));
assertThat(documentContext.read("$.persons[0].adults[1].age"), is(36));
assertThat(documentContext.read("$.persons.length()"), is(1));
assertThat(documentContext.read("$.persons[0].adults.length()"), is(2));

Or, alternatively you could use json-path-assert on top of JsonPath to add Hamcrest matchers like so:

assertThat(json, hasJsonPath("$.persons[0].adults[0].name", is("John")));
assertThat(json, hasJsonPath("$.persons[0].adults[1].age", is(36)));

Maven co-ordinates:

<!-- jayway jsonpath -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.3.0</version>
    <scope>test</scope>
</dependency>

<!-- json-path-assert -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path-assert</artifactId>
    <version>2.2.0</version>
    <scope>test</scope>
</dependency>
like image 187
glytching Avatar answered Oct 11 '22 15:10

glytching


There is an alternative way of validating JSON reply against expected value. You can use JSONassert

Example:

final MvcResult result = mockMvc.perform(get("/"))
                                .andDo(print())
                                .andExpect(status().isOk())
                                .andReturn();

final String json = result.getResponse().getContentAsString();
final String expected = "{field:'value', anotherField:true}";

JSONAssert.assertEquals(expected, json, true);

JSONassert provides several validation modes including custom comparators.

It is very convenient way of validating JSON output. In many cases it significantly reduces size unit test classes and give you visual representation of an expected JSON object.

like image 2
Tom Avatar answered Oct 11 '22 15:10

Tom