Search code examples
springspring-mvcspring-testjsonpathmockmvc

JsonPath config for MockMvc


JsonPath itself can be configured like this

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;

// ...

Configuration configuration = Configuration
    .builder()
    .options(Option.REQUIRE_PROPERTIES)
    .build();

JsonPath
    .using(configuration)
    .parse(someJson)
    .read("$.*.bar");

The example above enables Option.REQUIRE_PROPERTIES configuration option, so it will throw an exception if path does not exist.

How to configure the same thing for jsonPath used by MockMvc in a spring boot project?

import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

// ...

mockMvc
    .perform(get("/test"))
    .andExpect(status().isOk())
    .andExpect(jsonPath("$.*.bar").isEmpty())  // How to configure this 'jsonPath'?

Update

See the following example:

Input

[
  {"animal": "cat", "meow": true},
  {"animal": "cat", "meow": true},
  {"animal": "cat", "bark": true}
]

Expression

jsonPath("$.[?(@.animal == 'cat')].meow").value(everyItem(equalTo(true))

This produces a "false positive" test result. How I could write the json path expression, as I expect this test to produce a failed result.


Solution

  • No, unfortunately, we can't configure JSONPath that fine, in context of spring-test-mockmvc.

    Proof (https://github.com/spring-projects/spring-framework/blob/main/spring-test/src/main/java/org/springframework/test/util/JsonPathExpectationsHelper.java#L61):

     this.jsonPath = JsonPath.compile(this.expression);
    

    "They" use (internally) a simpler instantiation (without configuration).

    (What is wrong with isEmpty(), do you need this exception?) There are also alternative matchers like:

    • doesNotExist()
    • doesNotHaveJsonPath()

    If we need this fine config + exact exception, we can still:

    • Use JsonPath directly (/as a bean) to:
    • parse (e.g.) from MvcResult.getResponse().getContentAsString()
    @Bean
    Configuration configuration()
     return Configuration
        .builder()
        .options(Option.REQUIRE_PROPERTIES)
        .build();
    }
    

    ..and then:

    @Autowired
    Configuration config;
    // ...
      MvcResult result = mockMvc
        .perform(get("/test"))
        .andExpect(status().isOk())
        .andReturn();
      // try/expect:
      JsonPath
        .using(config)
        .parse(result.getResponse().getContentAsString())
        .read("$.*.bar"); 
    

    Refs: