1. Обзор
В этой короткой статье мы рассмотрим, как исключения должны создаваться в наших контроллерах и как протестировать эти исключения с помощью Spring MockMvc.
2. Создание исключений в контроллерах
Давайте начнем изучать как запустить исключение из контроллера .
Мы можем думать об услугах, которые мы предоставляем с контроллера, так же, как если бы они были обычными функциями Java:
@GetMapping("/exception/throw") public void getException() throws Exception { throw new Exception("error"); }
Теперь давайте посмотрим, что произойдет, когда мы вызовем эту службу. Во-первых, мы заметим, что код ответа службы равен 500, что означает внутреннюю ошибку сервера.
Во-вторых, мы получаем такой ответный орган, как этот:
{ "timestamp": 1592074599854, "status": 500, "error": "Internal Server Error", "message": "No message available", "trace": "java.lang.Exception at com.baeldung.controllers.ExceptionController.getException(ExceptionController.java:26) ..." }
В заключение, когда мы создаем исключение из RestController , ответ службы автоматически сопоставляется с кодом ответа 500, а трассировка стека исключения включается в тело ответа.
3. Сопоставление исключений с кодами ответов HTTP
Теперь мы собираемся узнать как сопоставлять наши исключения с различными кодами ответов кроме 500.
Для достижения этой цели мы собираемся создать пользовательские исключения и использовать аннотацию ResponseStatus , предоставленную Spring. Давайте создадим эти пользовательские исключения:
@ResponseStatus(HttpStatus.BAD_REQUEST) public class BadArgumentsException extends RuntimeException { public BadArgumentsException(String message) { super(message); } }
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public class InternalException extends RuntimeException { public InternalException(String message) { super(message); } }
@ResponseStatus(HttpStatus.NOT_FOUND) public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } }
Второй и последний шаг-создать простую службу в нашем контроллере, чтобы создавать эти исключения:
@GetMapping("/exception/{exception_id}") public void getSpecificException(@PathVariable("exception_id") String pException) { if("not_found".equals(pException)) { throw new ResourceNotFoundException("resource not found"); } else if("bad_arguments".equals(pException)) { throw new BadArgumentsException("bad arguments"); } else { throw new InternalException("internal error"); } }
Теперь давайте посмотрим различные ответы службы на различные исключения, которые мы сопоставили:
- Для not_found мы получаем код ответа 404
- Учитывая значение bad_arguments , мы получаем код ответа 400
- Для любого другого значения мы по-прежнему получаем 500 в качестве кода ответа
Помимо кодов ответов, мы получим текст в том же формате, что и текст ответа, полученный в предыдущем разделе.
4. Тестирование Наших Контроллеров
Наконец, мы увидим как проверить, что наш контроллер выдает правильные исключения .
Первым шагом является создание тестового класса и создание экземпляра MockMvc :
@Autowired private MockMvc mvc;
Далее давайте создадим тестовые примеры для каждого из значений, которые может получить наш сервис:
@Test public void givenNotFound_whenGetSpecificException_thenNotFoundCode() throws Exception { String exceptionParam = "not_found"; mvc.perform(get("/exception/{exception_id}", exceptionParam) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()) .andExpect(result -> assertTrue(result.getResolvedException() instanceof ResourceNotFoundException)) .andExpect(result -> assertEquals("resource not found", result.getResolvedException().getMessage())); } @Test public void givenBadArguments_whenGetSpecificException_thenBadRequest() throws Exception { String exceptionParam = "bad_arguments"; mvc.perform(get("/exception/{exception_id}", exceptionParam) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isBadRequest()) .andExpect(result -> assertTrue(result.getResolvedException() instanceof BadArgumentsException)) .andExpect(result -> assertEquals("bad arguments", result.getResolvedException().getMessage())); } @Test public void givenOther_whenGetSpecificException_thenInternalServerError() throws Exception { String exceptionParam = "dummy"; mvc.perform(get("/exception/{exception_id}", exceptionParam) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isInternalServerError()) .andExpect(result -> assertTrue(result.getResolvedException() instanceof InternalException)) .andExpect(result -> assertEquals("internal error", result.getResolvedException().getMessage())); }
С помощью этих тестов мы проверяем, что код ответа, тип вызванного исключения и сообщения об этих исключениях являются ожидаемыми для каждого из значений.
5. Заключение
В этом уроке мы узнали, как обрабатывать исключения в нашем Spring RestController s и как проверить, что каждая открытая служба выдает ожидаемые исключения.
Как всегда, полный исходный код статьи доступен в GitHub .