使用SpringMVC测试测试SpringMVC@ExceptionHandler方法

使用SpringMVC测试测试SpringMVC@ExceptionHandler方法,spring,spring-mvc,mockito,spring-mvc-test,Spring,Spring Mvc,Mockito,Spring Mvc Test,我有以下简单的控制器来捕获任何意外的异常: @ControllerAdvice public class ExceptionController { @ExceptionHandler(Throwable.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public ResponseEntity handleException(Throwable ex)

我有以下简单的控制器来捕获任何意外的异常:

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(Throwable.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ResponseEntity handleException(Throwable ex) {
        return ResponseEntityFactory.internalServerErrorResponse("Unexpected error has occurred.", ex);
    }
}
我正在尝试使用SpringMVC测试框架编写一个集成测试。这就是我到目前为止所做的:

@RunWith(MockitoJUnitRunner.class)
public class ExceptionControllerTest {
    private MockMvc mockMvc;

    @Mock
    private StatusController statusController;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new ExceptionController(), statusController).build();
    }

    @Test
    public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {

        when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));

        mockMvc.perform(get("/api/status"))
                .andDo(print())
                .andExpect(status().isInternalServerError())
                .andExpect(jsonPath("$.error").value("Unexpected Exception"));
    }
}
我在SpringMVC基础设施中注册ExceptionController和模拟StatusController。 在测试方法中,我设置了从StatusController引发异常的期望

正在抛出异常,但ExceptionController没有处理它

我希望能够测试ExceptionController是否获取异常并返回适当的响应

你有没有想过为什么这样不行,我应该怎么做这种测试


谢谢。

由于您使用的是单机安装测试,因此需要手动提供异常处理程序

mockMvc= MockMvcBuilders.standaloneSetup(adminCategoryController).setSingleView(view)
        .setHandlerExceptionResolvers(getSimpleMappingExceptionResolver()).build();
几天前我也遇到过同样的问题,你可以在这里看到我的问题和解决方案

希望我的回答能帮助你

试试看

@RunWith(value = SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { MVCConfig.class, CoreConfig.class, 
        PopulaterConfiguration.class })
public class ExceptionControllerTest {

    private MockMvc mockMvc;

    @Mock
    private StatusController statusController;

    @Autowired
    private WebApplicationContext wac;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void checkUnexpectedExceptionsAreCaughtAndStatusCode500IsReturnedInResponse() throws Exception {

        when(statusController.checkHealth()).thenThrow(new RuntimeException("Unexpected Exception"));

        mockMvc.perform(get("/api/status"))
                .andDo(print())
                .andExpect(status().isInternalServerError())
                .andExpect(jsonPath("$.error").value("Unexpected Exception"));
    }
}

此代码将添加使用异常控制建议的功能

@Before
public void setup() {
    this.mockMvc = standaloneSetup(commandsController)
        .setHandlerExceptionResolvers(withExceptionControllerAdvice())
        .setMessageConverters(new MappingJackson2HttpMessageConverter()).build();
}

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

我也有同样的问题,我的作品如下:

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(statusController)
         .setControllerAdvice(new ExceptionController())
        .build();
}
这样更好:

((HandlerExceptionResolverComposite) wac.getBean("handlerExceptionResolver")).getExceptionResolvers().get(0)
不要忘记在@Configuration类中扫描@ControllerAdvice bean:

@ComponentScan(basePackages = {"com.company.exception"})

…在Spring 4.0.2上测试。发布版

使用Spring MockMVC模拟servletContainer,使您可以将任何请求过滤或异常处理测试合并到单元测试套件中

您可以使用以下方法配置此设置:

给定自定义RecordNotFound异常

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Record not found") //
public class RecordNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 8857378116992711720L;

    public RecordNotFoundException() {
        super();
    }

    public RecordNotFoundException(String message) {
        super(message);
    }
}
。。。和RecordNotFoundExceptionHandler

@Slf4j
@ControllerAdvice
public class BusinessExceptionHandler {

    @ExceptionHandler(value = RecordNotFoundException.class)
    public ResponseEntity<String> handleRecordNotFoundException(
            RecordNotFoundException e,
            WebRequest request) {
         //Logs
        LogError logging = new LogError("RecordNotFoundException",
                HttpStatus.NOT_FOUND, 
                request.getDescription(true));
        log.info(logging.toJson());

        //Http error message
        HttpErrorResponse response = new HttpErrorResponse(logging.getStatus(), e.getMessage());
        return new ResponseEntity<>(response.toJson(),
                HeaderFactory.getErrorHeaders(),
                response.getStatus());
    }
   ...
}
配置模拟MVC“servlet emulator”:在上下文中注册处理程序bean并构建模拟MVC emulator(注意:有两种可能的配置:standaloneSetup或webAppContextSetup;请参阅)。生成器正确地实现了生成器模式,因此您可以在调用build()之前为异常解析程序和处理程序链接配置命令

获取异常解析程序

private ExceptionHandlerExceptionResolver getExceptionResolver(
        StaticApplicationContext context) {
    ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
    resolver.getMessageConverters().add(
            new MappingJackson2HttpMessageConverter());
    resolver.setApplicationContext(context);
    resolver.afterPropertiesSet();
    return resolver;
}
运行您的测试

    @Test
    public void testGetSingleOrganisationRecordAnd404() throws Exception {
        System.out.println("testGetSingleOrganisationRecordAndSuccess");
        String request = "/orgs/{id}";
        log.info("Request URL: " + request);

        when(service.getOrganisation(anyString())).
                thenReturn(coorg);
        this.mvc.perform(get(request)
                .accept("application/json")
                .andExpect(content().contentType(
                        .APPLICATION_JSON))
                .andExpect(status().notFound())
                .andDo(print());
    }
    ....
}
希望这有帮助


杰克。

我也有同样的问题;这对我很有用:

*thenThrow()中的运行时异常;ErrorHandler不会捕获异常或可丢弃的父类。
*删除正在测试的方法的所有try-catch语句
*根本不需要@Before或@ComponentScan注释

when(getRejectionQuery.execute(anyInt(), anyInt(), anyMap())).thenThrow(new RuntimeException());

我猜在测试中,异常处理程序没有被分配,不知道确切的原因,但这就是它发生的原因,看看这个答案,有什么消息吗?我也遇到了同样的情况,我没有找到解决办法。我决定相信@ExceptionHandler是有效的,因为方法本身很简单,所以我决定不用测试注释就可以生存。您仍然可以使用常规的单元测试来测试该方法。您的异常可能扩展了Throwable而不是exception。我遇到了同样的问题,并检查了InvocableHandlerMethod中的代码,该方法检查以下
else if(targetException instanceof Exception){throw(Exception)targetException;}
检查解决方案是否有帮助。将$.error替换为$.Message代码中包含getExceptionResolver()函数的包是什么?@Dhana解析了缺少的解析器getter。谢谢你升旗。
    @Test
    public void testGetSingleOrganisationRecordAnd404() throws Exception {
        System.out.println("testGetSingleOrganisationRecordAndSuccess");
        String request = "/orgs/{id}";
        log.info("Request URL: " + request);

        when(service.getOrganisation(anyString())).
                thenReturn(coorg);
        this.mvc.perform(get(request)
                .accept("application/json")
                .andExpect(content().contentType(
                        .APPLICATION_JSON))
                .andExpect(status().notFound())
                .andDo(print());
    }
    ....
}
when(getRejectionQuery.execute(anyInt(), anyInt(), anyMap())).thenThrow(new RuntimeException());