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?

1
  • I would love to know an answer to this! Commented Mar 13, 2017 at 19:15

2 Answers 2

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())))
Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.