Тестовый модуль Spring Controller генерирует исключение NestedServletException - PullRequest
2 голосов
/ 23 сентября 2019

У меня есть контроллер Spring, который выдает ошибку, когда нет данных.Я хочу проверить исключение, которое является пользовательским NoDataFoundException, но оно всегда выдает org.springframework.web.util.NestedServletException

Сообщение об ошибке модульного теста: java.lang.Exception: Unexpected exception, expected<com.project.NoDataFoundException> but was<org.springframework.web.util.NestedServletException>

Проверка модуля контроллера

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {MockConfiguration.class})
@WebAppConfiguration
public class ModelControllerTest{

    private MockMvc mockMvc;

    @Inject
    private ModelController controller;

    @Inject
    private ResponseBuilder responseBuilder;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }

    @Test(expected = NoDataFoundException.class)
    public void findAllModels_invalidRequest_throwNoDataFound() throws Exception {
        when(responseBuilder.findAll(any())).thenReturn(null);
        mockMvc
        .perform(get("/models"))
            .andExpect(status().isInternalServerError());
    }

}

Контроллер

@GetMapping("/models")
public ResponseEntity<List<Model>> findAllModels() {
    //Some Logic 
    dataExistenceCheck(response);
    return new ResponseEntity<>(response, HttpStatus.OK);
}

private <T> void dataExistenceCheck(T target) {
    if (target == null || (target instanceof Collection && ((Collection<?>) target).isEmpty())) {
        throw new NoDataFoundException();
    }
}

NoDataFoundException Class

public class NoDataFoundException extends RuntimeException {

    private static final long serialVersionUID = 140836818081224458L;

    public NoDataFoundException() {
        super();
    }

    public NoDataFoundException(String message) {
        super(message);
    }

}

Поиск

Я отлаживал коды и отслеживал до класса org.springframework.web.servlet.FrameworkServlet.Да, я ожидал NoDataFoundException, но там он выдает NesteServletException.

Как я могу решить это?Что я сделал не так?

enter image description here


Отредактированный вопрос

У меня @ControllerAdvice иобрабатывать NoDataFoundException, но он достигает NestedServletException, прежде чем достичь здесь.

@ResponseBody
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@ExceptionHandler(NoDataFoundException.class)
public ResponseEntity<ErrorResponse> noDataFoundExceptionHandler(NoDataFoundException exception) {
    LOGGER.debug("No data found exception [{}].", exception);
    return new ResponseEntity<>(new ErrorResponse("not found"), HttpStatus.NOT_FOUND);
}   

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

NestedServletException - это оболочка / адаптер, который принимает все исключения к javax.servlet.ServletException.Это часть API Java-сервлетов.

Вы можете решить эту проблему следующими способами:

1) Поймать NestedServletException и вызвать повторный бросок:

try {
    mockMvc
    .perform(get("/models"))
        .andExpect(status().isInternalServerError());
} catch (NestedServletException e) {
    throw e.getCause();
}

2) Использовать org.assertj.core.api.Assertions.assertThatThrownBy

@Test
public void findAllModels_invalidRequest_throwNoDataFound() throws Throwable {
    Assertions.assertThatThrownBy(() ->
            mockMvc.perform(get("/models")).andExpect(status().isInternalServerError()))
            .hasCause(new NoDataFoundException(null));
}

3) В вашем контроллере или глобальном обработчике исключений добавьте @ExceptionHandler(NoDataFoundException.class) и переведите его в действительный код Http и тело ответа.

4) Расширяет NoDataFoundException с ServletException

1 голос
/ 25 сентября 2019

Я вижу два варианта для вас:

  1. Сделайте ваш NoDataFoundException расширение ServletException.Я не уверен, что он подойдет вам, потому что это сделает ваше исключение проверенным.
  2. Используйте другой подход, чтобы проверить, какое исключение было сгенерировано, например там

На самом деле, лучше всегда писать такого рода тесты согласно второму варианту, потому что согласно Спецификация сервлета :

Сервлет или фильтр могут выдавать следующие исключения во время обработкизапроса:

  1. исключения или ошибки времени выполнения
  2. ServletException или его подклассы
  3. IOExceptions или их подклассы

PS: Если вас интересуют причины, по которым Spring обрабатывает исключения таким образом, я задал вопрос

...