我有一个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
。
我该如何解决?我做错了什么?
已编辑的问题
我有@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);
}
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
我为您提供了两种选择:
ServletException
扩展为NoDataFoundException
。我不确定是否适合您,因为它将检查您的异常。ServletException
实际上,最好总是根据第二个选项编写测试,因为根据there:
一个servlet或过滤器可能会在处理请求:
- 运行时异常或错误
- ServletExceptions或其子类
- IOExceptions或其子类
PS:如果您对为什么Spring以这种方式处理异常的原因感兴趣,我问了Servlet Specification