测试控制器中抛出的异常

时间:2015-04-01 08:45:52

标签: java unit-testing spring-mvc

我想对抛出异常的控制器方法执行测试。方法是这样的:

@RequestMapping("/do")
public ResponseEntity doIt(@RequestBody Request request) throws Exception {
    throw new NullPointerException();
}

当我尝试使用以下代码部分测试此方法时,

 mockMvc.perform(post("/do")
                .contentType(MediaType.APPLICATION_JSON)
                .content(JSON.toJson(request)))
从Spring库中抛出

NestedServletException。如何测试NullPointerException而不是NestedServletException

2 个答案:

答案 0 :(得分:1)

我们的解决方案是一种解决方法:在建议中捕获异常,并将错误体作为HTTP响应返回。以下是模拟的工作原理:

MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller)
                        .setHandlerExceptionResolvers(withExceptionControllerAdvice())
                        .build();

private ExceptionHandlerExceptionResolver withExceptionControllerAdvice() {
    final ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
        @Override
        protected ServletInvocableHandlerMethod getExceptionHandlerMethod(final HandlerMethod handlerMethod, final Exception exception) {
            Method method = new ExceptionHandlerMethodResolver(TestAdvice.class).resolveMethod(exception);
            if (method != null) {
                return new ServletInvocableHandlerMethod(new TestAdvice(), method);
            }
            return super.getExceptionHandlerMethod(handlerMethod, exception);
        }
    };
    exceptionResolver.afterPropertiesSet();
    return exceptionResolver;
}

咨询类:

@ControllerAdvice
public class TestAdvice {
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object exceptionHandler(Exception e) {
        return new HttpEntity<>(e.getMessage());
    }
}

之后,以下测试方法成功通过:

@Test
public void testException
    mockMvc.perform(post("/exception/path"))
        .andExpect(status().is5xxServerError())
        .andExpect(content().string("Exception body"));
}

答案 1 :(得分:1)

更简单的方法是将@ExceptionHandler注入到Spring Test Context中,或者在MockMvc.perform()之前的.andExpect()中抛出异常。

@ContextConfiguration(classes = { My_ExceptionHandler_AreHere.class })
@AutoConfigureMockMvc
public class Test {
    @Autowired
    private MockMvc mvc;

    @Test
    public void test() {
        RequestBuilder requestBuilder = MockMvcRequestBuilders.post("/update")
                .param("branchId", "13000")
                .param("triggerId", "1");
        MvcResult mvcResult = mvc.perform(requestBuilder)
                .andExpect(MockMvcResultMatchers.status().is4xxClientError())
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(__ -> Assert.assertThat(
                        __.getResolvedException(),
                        CoreMatchers.instanceOf(SecurityException.class)))
                .andReturn();
}

这样MvcResult.getResolvedException()保留@Controller的例外!

https://stackoverflow.com/a/61016827/173149