Spring控制器单元测试抛出NestedServletException

问题描述 投票:1回答:2

我有一个Spring控制器,当没有数据时会抛出错误。我想测试异常,这是自定义NoDataFoundException,但总是抛出org.springframework.web.util.NestedServletException

单元测试错误消息是:java.lang.Exception: Unexpected exception, expected<com.project.NoDataFoundException> but was<org.springframework.web.util.NestedServletException>

控制器单元测试

@RunWith(SpringJUnit4ClassRunner.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类

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);
}   
java spring-boot junit4 mockmvc
2个回答
1
投票

NestedServletException是采用javax.servlet.ServletException的所有异常的包装器/适配器。它是Java Servlet API的一部分。

您可以通过以下方式解决它:

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扩展[C0


1
投票

我为您提供了两种选择:

  1. 使ServletException扩展为NoDataFoundException。我不确定是否适合您,因为它将检查您的异常。
  2. 使用另一种方法来检查抛出了什么异常,例如ServletException

实际上,最好总是根据第二个选项编写测试,因为根据there

一个servlet或过滤器可能会在处理请求:

  1. 运行时异常或错误
  2. ServletExceptions或其子类
  3. IOExceptions或其子类

PS:如果您对为什么Spring以这种方式处理异常的原因感兴趣,我问了Servlet Specification

© www.soinside.com 2019 - 2024. All rights reserved.