testing an error response with MockMvc and jsonPath()
Asked Answered
B

2

6

I'm trying to test an Spring MVC controller's error response with the following

this.mockMvc
    .perform(get("/healthChecks/9999"))
    .andExpect(status().isNotFound())
    .andExpect(jsonPath('error', is("Not Found")))
    .andExpect(jsonPath('timestamp', is(notNullValue())))
    .andExpect(jsonPath('status', is(404)))
    .andExpect(jsonPath('path', is(notNullValue())))

but the test is failing with the exception: java.lang.IllegalArgumentException: json can not be null or empty on the first jsonPath assertion.

When I curl this URL, I get the following:

{
  "timestamp": 1470242437578,
  "status": 200,
  "error": "OK",
  "exception": "gov.noaa.ncei.gis.web.HealthCheckNotFoundException",
  "message": "could not find HealthCheck 9999.",
  "path": "/healthChecks/9999"
}

Can someone please help me understand what I'm doing wrong?

Brittabrittain answered 3/8, 2016 at 16:43 Comment(1)
I would love to know an answer to this!Freewill
C
1

You write incorrect JsonPath expressions (For More Information LINK), use $ for root path. In your case it should look like:

.andExpect(jsonPath('$.error', is("Not Found")))
.andExpect(jsonPath('$.timestamp', is(notNullValue())))
.andExpect(jsonPath('$.status', is(404)))
.andExpect(jsonPath('$.path', is(notNullValue())))
Circumcision answered 25/5, 2018 at 5:19 Comment(0)
K
0

Short answer:

MockMvc does not use a real servlet container which dipatches error mappings to an ErrorController. So, use @SpringBootTest configured with a DEFINED_PORT or RANDOM_PORT web environment and TestRestTemplate.

Long answer:

The quote is from the discussion in this issue

Spring Boot's error handling is based on Servlet container error mappings that result in an ERROR dispatch to an ErrorController. MockMvc however is container-less testing so with no Servlet container the exception simply bubbles up with nothing to stop it.

So MockMvc tests simply aren't enough to test error responses generated through Spring Boot. I would argue that you shouldn't be testing Spring Boot's error handling. If you're customizing it in any way you can write Spring Boot integration tests (with an actual container) to verify error responses. And then for MockMvc tests focus on fully testing the web layer while expecting exceptions to bubble up.

This is a typical unit vs integration tests trade off. You do unit tests even if they don't test everything because they give you more control and run faster.

Klimt answered 4/7, 2022 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.