0

As part of my JHipster-generated Spring Boot app, I'm trying to adapt an integration test to ensure that the return JSON object contains null for a particular property:

import static org.springframework.test.web.servlet.ResultActions.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

.andExpect(jsonPath("$.selectedChannels[0].channelValue")
    .doesNotExist())

This doesn't seem to work. For the response:

{
    "selectedChannels": [{
        "name": "test channel",
        "channelValue": null
    }]
}

I would get a response:

java.lang.AssertionError: Expected no value at JSON path "$.selectedChannels[0].channelValue" but found: [null]

I suppose the "doesNotExist" call is trying to make sure that the key does not exist. I tried using "value" as well with a null value but this just throws a NPE. How do I perform this assertion successfully?

2 Answers 2

1

The JSON Path Matcher doesNotExist() is intented to be used to assert that no key is present. For your example the key channelValue is present and therefore the assertion fails. See also official Javadocs (https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/servlet/result/JsonPathResultMatchers.html#doesNotExist--) for JsonPathResultMatchers doesNotExist():

Evaluate the JSON path expression against the response content and assert that a value does not exist at the given path.

What you want for your provided response is checking if the response contains a null value for the key channelValue:

resultActions.andExpect(jsonPath("$.selectedChannels[0].channelValue").value(nullValue());

Make sure to add a static import for Hamcrest nullValue() matcher: import static org.hamcrest.Matchers.nullValue;

Sign up to request clarification or add additional context in comments.

3 Comments

I don't see a static method for nullValue mentioned in any of the libraries I have referenced. Can you direct me to its proper location?
It is a Hamcrest matcher with should already part of your JHipster applicatio. Import with import static org.hamcrest.Matchers.nullValue;
Ah, that particular matcher does not work: org.hamcrest.core.IsNull.nullValue() returns the response: Expected: null but: was <[null]>. Spring's JsonPathResultMatchers is casting null to a list of null for some reason.
1

I believe there may be some bug that causes Spring Framework (Spring Boot version 1.5.4 currently) to render the null value as a net.minidev.json.JSONArray with a single value of null. So "channelValue": null is rendered to "channelValue": [null]. This prevents the nullValue matcher from working.

Currently the only solution I could muster to this problem was to implement and use my own Matcher. Using the NullValue matcher as a template I have this:

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import net.minidev.json.JSONArray;

/**
 * Matcher that can be used to detect if a value is null or refers to an empty list,
 * or a list that contains a single null value. 
 *
 * @param <T>
 */
public class IsNullOrEmpty<T> extends BaseMatcher<T> {

    @Override
    public boolean matches(Object item) {
        System.out.println(item.getClass().getPackage());
        if(item instanceof JSONArray) {
            JSONArray arr = ((JSONArray)item);
            return arr==null || arr.size()==0 || (arr.size()==1 && arr.get(0)==null);
        }
        return item==null;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("null or list of null");
    }

    /**
     * Detect if the value is null or contains an empty array, or an array of a single element
     * of null
     * @return
     */
    public static Matcher<Object> isNullOrEmpty() {
        return new IsNullOrEmpty<>();
    }

}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.