MockMvc断言LocalDateTime与List类型匹配失败问题咨询
核心原因
MockMvc的JsonPath断言默认只会将JSON返回值解析为Java原生基础类型、字符串、Map、List结构,不会自动反序列化为自定义POJO类、LocalDateTime这类JDK扩展类型,两边类型不匹配自然会抛出断言错误。
两个错误的具体说明与解决
1. LocalDateTime类型断言错误
错误原因:JSON本身没有原生时间类型,序列化后返回的createdAt是ISO格式的字符串,JsonPath读取出的实际值是String类型,和你传入的LocalDateTime对象类型不一致,即使字面量相同也会判定不相等。
最简单的解决方式:直接将预期的LocalDateTime转为对应格式的字符串再对比:
.andExpect(jsonPath("$.createdAt", is(control.getCreatedAt().toString())))
如果你的接口配置了自定义时间序列化格式,用对应的DateTimeFormatter把LocalDateTime转成对应字符串即可。
2. Set类型断言错误
错误原因:JsonPath读取到的scenarios实际是List<Map<String,Object>>结构,每个元素是键值对形式的Map,和你传入的自定义Scenario对象属于完全不同的类型,equals对比直接失败;另外即使实现了自动反序列化,你的Scenario类没有重写equals和hashCode方法,也会导致对象对比不通过。
两种可选解决方案:
- 方案一(无需额外配置,推荐):拆分断言集合的各个字段
.andExpect(jsonPath("$.scenarios.length()", is(2))) .andExpect(jsonPath("$.scenarios[0].id", is(1))) .andExpect(jsonPath("$.scenarios[0].name", is("Max"))) .andExpect(jsonPath("$.scenarios[1].id", is(2))) .andExpect(jsonPath("$.scenarios[1].name", is("Average")))
- 方案二:直接将整个响应体反序列化为Control对象后对比
先给Control、Scenario类重写equals和hashCode方法,再按如下方式写断言:
MvcResult result = mockMvc.perform(get("/control/find/" + control.getId())) .andExpect(status().isOk()) .andReturn(); // 注意ObjectMapper要注册JavaTimeModule支持LocalDateTime反序列化 ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule()); Control respControl = objectMapper.readValue(result.getResponse().getContentAsString(), Control.class); assertEquals(control, respControl);
修改后的完整断言示例(无需额外配置)
mockMvc.perform(get("/control/find/" + control.getId())) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("$.id", equalTo(control.getId()), Long.class)) .andExpect(jsonPath("$.name", equalTo(control.getName()))) .andExpect(jsonPath("$.createdAt", is(control.getCreatedAt().toString()))) .andExpect(jsonPath("$.scenarios.length()", is(2))) .andExpect(jsonPath("$.scenarios[0].id", is(1))) .andExpect(jsonPath("$.scenarios[0].name", is("Max"))) .andExpect(jsonPath("$.scenarios[1].id", is(2))) .andExpect(jsonPath("$.scenarios[1].name", is("Average")));
内容的提问来源于stack exchange,提问作者VeryNiceArgumentException
相关产品推荐
相关产品推荐

