Spring 6.1升级后请求参数校验测试失败问题求助
解决方案
问题根源
Spring Boot 3.2.x(基于Spring Framework 6.1+)引入了HandlerMethodValidationException专门处理方法参数验证错误,且默认不再自动将该异常转换为400 Bad Request响应,而是直接抛出异常,导致原有测试中预期400状态的断言失效。
最快优雅的解决方法(二选一即可)
方法1:调整测试代码,直接验证异常(无需修改业务代码)
利用Spring MVC Test提供的匹配器,直接断言验证异常的存在及细节,替代原有对响应内容的硬编码断言:
mvc.perform(get(ENDPOINT) .queryParam("myparam", "100")) .andExpect(status().isBadRequest()) .andExpect(handler().handlerMethodValidationError()) .andExpect(result -> { HandlerMethodValidationException ex = (HandlerMethodValidationException) result.getResolvedException(); // 验证具体的错误字段和提示信息 assertThat(ex.getAllValidationResults()).hasSize(1); var fieldError = ex.getAllValidationResults().get(0).getFieldErrors().get(0); assertThat(fieldError.getField()).isEqualTo("myparam"); assertThat(fieldError.getDefaultMessage()).isEqualTo("size must be between 0 and 10"); });
方法2:在测试中临时添加异常处理器(保留原有测试断言)
如果希望完全复用原有测试的响应断言,可在构建MockMvc时添加临时的异常处理器,将HandlerMethodValidationException转换为预期的400响应:
// 构建MockMvc时添加异常处理逻辑 mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) .setHandlerExceptionResolvers((request, response, handler, ex) -> { if (ex instanceof HandlerMethodValidationException) { response.setStatus(HttpStatus.BAD_REQUEST.value()); response.setContentType(APPLICATION_PROBLEM_JSON_VALUE); // 写入原有测试预期的JSON内容 try (PrintWriter writer = response.getWriter()) { writer.write(""" { "type": "/problems/validation-error", "title": "The request parameters didn't validate", "instance": "my-endpoint", "status": 400, "errors": [ { "path":"myparam","message":"size must be between 0 and 10" } ] } """); } catch (IOException e) { throw new RuntimeException(e); } return new ModelAndView(); } return null; }) .build(); // 原有测试代码无需修改,可直接运行 mvc.perform(get(ENDPOINT) .queryParam("myparam", "100")) .andExpectAll( status().isBadRequest(), content().contentType(APPLICATION_PROBLEM_JSON), content().json(""" { "type": "/problems/validation-error", "title": "The request parameters didn't validate", "instance": "my-endpoint", "status": 400, "errors": [ { "path":"myparam","message":"size must be between 0 and 10" } ] } """, true));
补充说明
如果希望业务代码也恢复升级前的响应行为(即全局自动处理该异常返回400+Problem JSON),可以添加一个@ControllerAdvice类统一处理,不过这属于业务代码变更,按需选择即可。
内容的提问来源于stack exchange,提问作者user3083022
相关产品推荐
相关产品推荐

