如何为MockMvc独立配置设置全局日期格式
解决MockMvc全局LocalDate日期格式解析问题
问题场景
我有一个Spring MVC接口,通过全局配置spring.mvc.format.date=iso统一处理请求中的LocalDate参数格式,但使用MockMvc的standaloneSetup编写测试用例时,ISO格式(如2022-01-01)的字符串无法转换为LocalDate对象。我不想给每个请求参数添加@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)注解,希望通过配置实现全局生效。
现有代码
接口端点
@GetMapping("/path") public ResponseDTO<Page<Program>> getProgramsByUserId(@PathVariable String userId, Pageable pageable, @RequestParam(required = false) LocalDate from, @RequestParam(required = false) LocalDate to) { return null; }
Spring全局配置
spring: mvc: format: date: iso
测试用例
@ExtendWith(MockitoExtension.class) class Test { private MockMvc mockMvc; @InjectMocks private Controller controller; private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach void setUp() { objectMapper.registerModule(new JavaTimeModule()); mockMvc = MockMvcBuilders .standaloneSetup(controller) .setControllerAdvice(new GlobalControllerAdvice()) .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver()) .build(); } @Test void test() throws Exception { //given var pageable = PageRequest.of(0, 5); var from = LocalDate.of(2022, 1, 1); var to = LocalDate.of(2022, 12, 31); MvcResult mvcResult = mockMvc.perform(get("/path") .param("page", pageable.getPageNumber() + "") .param("size", pageable.getPageSize() + "") .param("from", from.toString()) .param("to", to.toString())) .andExpect(status().isOk()) .andReturn(); } }
解决方案
方案1:加载完整Spring上下文(推荐,配置自动生效)
将测试类改为使用@SpringBootTest和@AutoConfigureMockMvc,让测试加载完整的Spring上下文,自动读取全局日期格式配置:
@SpringBootTest @AutoConfigureMockMvc class Test { @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; @Test void test() throws Exception { var pageable = PageRequest.of(0, 5); var from = LocalDate.of(2022, 1, 1); var to = LocalDate.of(2022, 12, 31); MvcResult mvcResult = mockMvc.perform(get("/path") .param("page", pageable.getPageNumber() + "") .param("size", pageable.getPageSize() + "") .param("from", from.toString()) .param("to", to.toString())) .andExpect(status().isOk()) .andReturn(); } }
方案2:手动配置MockMvc的格式化服务
如果不想加载完整Spring上下文,可在standaloneSetup中手动构建并设置FormattingConversionService,模拟全局ISO日期格式配置:
@ExtendWith(MockitoExtension.class) class Test { private MockMvc mockMvc; @InjectMocks private Controller controller; private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach void setUp() { objectMapper.registerModule(new JavaTimeModule()); // 构建全局格式化服务,配置ISO日期格式 FormattingConversionService conversionService = new DefaultFormattingConversionService(); DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); registrar.setDateFormatter(DateTimeFormatter.ISO_LOCAL_DATE); registrar.registerFormatters(conversionService); mockMvc = MockMvcBuilders .standaloneSetup(controller) .setControllerAdvice(new GlobalControllerAdvice()) .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver()) .setConversionService(conversionService) // 注入格式化服务 .build(); } @Test void test() throws Exception { var pageable = PageRequest.of(0, 5); var from = LocalDate.of(2022, 1, 1); var to = LocalDate.of(2022, 12, 31); MvcResult mvcResult = mockMvc.perform(get("/path") .param("page", pageable.getPageNumber() + "") .param("size", pageable.getPageSize() + "") .param("from", from.toString()) .param("to", to.toString())) .andExpect(status().isOk()) .andReturn(); } }
说明:standaloneSetup模式下不会自动读取Spring的全局配置,需要手动配置ConversionService来实现和spring.mvc.format.date=iso相同的效果。
内容的提问来源于stack exchange,提问作者eternal
相关产品推荐
相关产品推荐

