4
votes

Long story short. My service, throws EntityNotFound exceptions. By default Spring boot doesn't know what kind exception is that and how to treat it and simply displays a "500 Internal Server Error".

I had no choice but implementing my own exception handling mechanism.

There are several ways to resolve this issue with Spring boot. And I chose to use the @ControllerAdvice with @ExceptionHandler methods.

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<ErrorDetails> handleNotFound(EntityNotFoundException exception, HttpServletRequest webRequest) {
    ErrorDetails errorDetails = new ErrorDetails(
            new Date(),
            HttpStatus.NOT_FOUND,
            exception,
            webRequest.getServletPath());

    return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
 }
}

So when the exception is being thrown, the new handler catches the exception and returns a nice json containing a message, like:

{
"timestamp": "2018-06-10T08:10:32.388+0000",
"status": 404,
"error": "Not Found",
"exception": "EntityNotFoundException",
"message": "Unknown employee name: test_name",
"path": "/assignments"
}

Implementing - not that hard. Hardest part is testing.

First of all, while testing spring doesn't seem to know of the new handler in test mode. How can i tell spring to be aware of a new implementation for handling such errors?

@Test
public void shouldShow404() throws Exception {
    mockMvc.perform(post("/assignments")
            .contentType(APPLICATION_JSON_UTF8_VALUE)
            .content(new ClassPathResource("rest/assign-desk.json").getInputStream().readAllBytes()))
            .andExpect(status().isNotFound());
}

As I see it, this test should pass but it doesn't.

Any thoughts are welcome. Thank You!

2
How are you initializing the test class? What runner are you using?raiyan
"@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc'code"D2k

2 Answers

1
votes

Found the answer.

For whom it may concern:

Settings apon class :

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class GlobalExceptionHandlerTest{
//
}

and the test:

@Test
public void catchesExceptionWhenEntityNotFoundWithSpecificResponse() throws Exception {

    mockMvc.perform(post("/assignments")
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .content(new ClassPathResource("rest/assign-desk.json").getInputStream().readAllBytes()))
            .andExpect(status().isNotFound())
            .andExpect(jsonPath("status").value(404))
            .andExpect(jsonPath("exception").value("EntityNotFoundException"))
            .andExpect(jsonPath("message").value("Unknown employee name: abc"));
}

Thank you all.

0
votes

Possible duplicate of question or github issue. Don't know how you setup your test class. But if you have your test class anotated with WebMvcTest, all controllers and controller advices should be registered.