MockMvc测试LocalDate请求参数触发MethodArgumentTypeMismatchException问题
解决MockMvc测试LocalDate参数类型不匹配异常
问题原因
你遇到的MethodArgumentTypeMismatchException是因为测试中传递的日期字符串格式,和Spring MVC解析LocalDate的格式不匹配。生产环境能正常工作,说明项目已经配置了对应的日期格式化规则(比如全局配置或参数注解),但测试环境没有加载到这些配置,导致无法将"10.10.2015"这类格式的字符串转换为LocalDate对象。
解决方案
方案1:给控制器参数显式添加日期格式化注解
直接在控制器的LocalDate参数上添加@DateTimeFormat注解,指定解析格式,确保生产和测试环境规则统一:
修改控制器代码:
@GetMapping("/") public ResponseEntity<List<TransactionDto>> getTransactionByDateRange( @RequestParam @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate startDate, @RequestParam @DateTimeFormat(pattern = "dd.MM.yyyy") LocalDate endDate) { logger.info("Get transaction request received with date range, start date: {} and end date: {}", startDate, endDate); List<TransactionDto> transactionDtoList = transactionService.findTransactionByDateRange(startDate, endDate); if(transactionDtoList.isEmpty()){ throw new TransactionListIsEmptyException("No transaction data can be found in this date range. " + "Please check the date range you entered."); } return new ResponseEntity(Response.ok().setPayload(transactionDtoList), HttpStatus.OK); }
方案2:确保测试环境加载全局日期格式化配置
如果你的项目是通过全局配置(比如application.properties中的spring.mvc.format.date-local=dd.MM.yyyy,或者自定义WebMvcConfigurer添加LocalDate转换器)支持日期格式的,需确保测试类加载这些配置:
- 若测试类用
@SpringBootTest:会自动加载全局配置,无需额外操作。 - 若测试类用
@WebMvcTest:需手动导入配置类,或给MockMvc添加自定义参数解析器,示例如下:
@WebMvcTest(TransactionController.class) public class TransactionControllerTest { @Autowired private TransactionController transactionController; private MockMvc mockMvc; @BeforeEach void setUp() { // 给MockMvc添加LocalDate参数解析器 mockMvc = MockMvcBuilders.standaloneSetup(transactionController) .setCustomArgumentResolvers(new LocalDateArgumentResolver()) .build(); } // 自定义LocalDate参数解析器,匹配dd.MM.yyyy格式 static class LocalDateArgumentResolver implements HandlerMethodArgumentResolver { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy"); @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().equals(LocalDate.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String paramName = parameter.getParameterName(); String paramValue = webRequest.getParameter(paramName); if (paramValue != null) { return LocalDate.parse(paramValue, FORMATTER); } return null; } } // 你的测试方法 @Test public void testfindTransactionByDateRange_whenTransactionsAreExists_ShouldReturnTransactionDtoList() throws Exception { // given部分代码不变 this.mockMvc.perform(get(TRANSACTION_API_ENDPOINT) .queryParam("startDate","10.10.2015") .queryParam("endDate","10.10.2015")) .andExpect(status().is2xxSuccessful()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } }
方案3:修改测试用的日期格式为Spring默认格式
Spring MVC默认的LocalDate解析格式是yyyy-MM-dd,你可以直接修改测试代码中的日期字符串为该格式,无需额外配置:
this.mockMvc.perform(get(TRANSACTION_API_ENDPOINT) .queryParam("startDate","2015-10-10") .queryParam("endDate","2015-10-10")) .andExpect(status().is2xxSuccessful()) .andExpect(content().contentType(MediaType.APPLICATION_JSON));
内容的提问来源于stack exchange,提问作者Mert Özler
相关产品推荐
相关产品推荐

