spring-mvc - 通过 Jackson2ObjectMapperBuilder 设置自定义日期格式导致请求处理在异常后继续
问题描述
我有一个 MockMvc 测试,用于测试控制器的 JSON 有效负载是否经过验证,并且为org.springframework.data.mapping.PropertyReferenceException
和呈现 HTTP 400(错误请求) org.springframework.http.converter.HttpMessageConversionException
。
相应的异常处理程序实现如下。
@ControllerAdvice
public class LocalExceptionHandler {
@ExceptionHandler(PropertyReferenceException.class)
public ResponseEntity<Object> handlePropertyReferenceException(PropertyReferenceException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(HttpMessageConversionException.class)
public ResponseEntity<Object> handleHttpMessageConversionException(HttpMessageConversionException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
我正在使用 Spock 规范来实现测试。设置如下。
MockMvc mvc
public JsonSerializer[] buildJsonSerializers() {
return new JsonSerializer[]{new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)),
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))};
}
Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
builder.simpleDateFormat(DATE_TIME_FORMAT);
builder.serializers(buildJsonSerializers());
};
}
protected ObjectMapper buildObjectMapper() {
def objectMapperBuilder = new Jackson2ObjectMapperBuilder()
jsonCustomizer().customize(objectMapperBuilder)
objectMapperBuilder.modules(new MoneyModule()
.withMonetaryAmount(Money::of)
.withAmountFieldName("number")
.withFormattedFieldName("pretty"))
objectMapperBuilder.build()
}
def setup() {
ObjectMapper mapper = buildObjectMapper()
def mockMvcBuilder = MockMvcBuilders
.standaloneSetup(controller)
.setControllerAdvice(LocalExceptionHandler.class)
.setMessageConverters([new MappingJackson2HttpMessageConverter(mapper)]
.toArray(new HttpMessageConverter[1]))
.setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
mvc = mockMvcBuilder.build()
}
所以上面的设置只是通过定制器设置日期格式,然后使用Jackson2ObjectMapperBuilder
.
该设置的问题在于构建器导致对象映射器配置导致奇怪的 MockMvc 行为。
当向控制器发布错误请求时,会引发适当的异常并由上述异常处理程序之一处理,但请求处理不会停止并调用控制器方法。当运行生产代码(作为 Spring Boot 应用程序)时,错误处理很好,导致 HTTP 400。
只需删除构建器并仅模仿测试所需的配置(这是正确的日期时间格式),测试就会按预期工作,并且在异常处理后停止请求处理。
所以基本上我没有使用构建器
def mapper = new ObjectMapper()
mapper.registerModule(new MoneyModule()
.withMonetaryAmount(Money::of)
.withAmountFieldName("number")
.withFormattedFieldName("pretty"))
SimpleModule serializerModule = new SimpleModule()
Arrays.asList(buildJsonSerializers())
.forEach({ s -> serializerModule.addSerializer(s.handledType(), s) })
mapper.registerModule(serializerModule)
所以看起来构建器正在添加一些 MockMvc 并没有真正正确处理的配置。将不胜感激有关解决此问题的提示。
解决方案
推荐阅读
- c - 为什么我的 C 程序会出错:警告:函数“回文”的隐式声明 [-Wimplicit-function-declaration]
- javascript - 我的编程语言的 Lexer 不会处理 NEWLINE(用 moo js 完成)
- java - testng的gradle错误:任务':app:test'的执行失败
- javascript - 比较两个数组并返回属性值等于另一个键数组的对象数组
- php - 类属性的值被清空
- amazon-web-services - terraform 在循环中调用模块
- google-apps-script - Google Apps 脚本测试未发布的插件
- java - 将地理位置添加到碎片谷歌地图
- dtd - 无法识别此 uri 注册的资源x mlns="http://www.xmlsecurity.org/NS/#configuration">
- shell - shell 函数 cd 中断 $PATH