Issue
So I am trying to send a customized answer when user is trying to call an url unknown to my application. To do that I first added to my application.properties (in both main and test folders)
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
So that if no handler is found an exception is thrown. This exception should be of type NoHandlerFoundException
Then I added in my controller advice a custom exception handler my controller advice (simplified)
@EnableWebMvc // (I tried with and without it doesn't change the error)
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE) // (I tried with and without it doesn't change the error)
public class ExceptionsHandler extends ResponseEntityExceptionHandler {
// invalid route handler
@Override
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
protected ResponseEntity<Object> handleNoHandlerFoundException(
NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String error = "No handler found for " + ex.getHttpMethod() + " " + ex.getRequestURL();
ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, ex.getLocalizedMessage(), error);
return new ResponseEntity<>(apiError.getErrors(), new HttpHeaders(), apiError.getStatus());
}
}
Using this, when calling an unknown url in my test using :
this.mvc.perform(get("/ttt"))
.andDo(print())
.andExpect(status().isNotFound())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.error").value("No Handler found for GET /ttt"));
I get in my debug console :
o.s.web.servlet.PageNotFound : No mapping for GET /ttt
Though, answer doesn't have my custom error message as I also get in my debug console :
MockHttpServletResponse:
Status = 404
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I then tried
@ExceptionHandler({NoHandlerFoundException.class})
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ResponseEntity<Object> handleNoHandler(HttpServletRequest request, Exception ex) {
String error = ex.getMessage();
return new ResponseEntity<>(error, new HttpHeaders(), HttpStatus.NOT_FOUND);
}
But then a Illegal state exception : Failed to load application context is thrown with cause
IllegalStateException:Ambiguous @ExceptionHandler method mapped for [class org.framework.web.servlet.NoHandlerFoundException]
ALso, When I put breakpoints in my handlers and debug my test, the execution never stops at any breakpoint.
Solution
So it seems that MockMvc has trouble with building MockHttpServletRequest when using exception handlers thus the empty content.
When I run my springboot application and try calling an unknown url in my navigator, It works. I have the expected error 404; with body : No handler found
using the override method.
see more here, stack accepted answer with 100+ usefulness score -> Unit test MockHttpServletRequest not returning content type
Answered By - eln
Answer Checked By - Gilberto Lyons (JavaFixing Admin)