ObjectMapper Mock与非Mock场景问题:Controller测试报错如何解决?
问题解决方案
核心问题在于控制器和测试代码对ObjectMapper的依赖需要协调处理,以下是具体解决思路和代码实现:
1. 先确保控制器的ObjectMapper注入正确
控制器必须通过Spring依赖注入获取ObjectMapper,而非自行实例化,这样测试时才能灵活控制其行为:
@RestController public class ItemController { private final ObjectMapper objectMapper; private final Logger logger = LoggerFactory.getLogger(ItemController.class); // 推荐构造注入方式,确保依赖可被测试替换 public ItemController(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @PostMapping("/api/items") public ResponseEntity<Void> createItem(@RequestBody Item item) { try { logger.info("Received item: {}", objectMapper.writeValueAsString(item)); } catch (JsonProcessingException e) { logger.error("Failed to serialize item", e); } // 业务逻辑实现 return ResponseEntity.ok().build(); } }
2. 单元测试的两种正确配置方式
方式一:使用@WebMvcTest自动配置(推荐)
Spring Boot的@WebMvcTest会自动配置MockMvc和默认的ObjectMapper实例,控制器和测试代码共用同一个实例,避免冲突:
@WebMvcTest(ItemController.class) class ItemControllerTest { @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; // 直接使用Spring管理的ObjectMapper @Test void testCreateItem() throws Exception { Item testItem = new Item("test-item", 100); mockMvc.perform(post("/api/items") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(testItem))) .andExpect(status().isOk()); } }
方式二:手动MockObjectMapper(特殊场景需求)
如果必须Mock控制器中的ObjectMapper,需为Mock实例配置正确的方法行为,避免控制器调用时抛出异常:
@WebMvcTest(ItemController.class) class ItemControllerTest { @Autowired private MockMvc mockMvc; @MockBean // 替换Spring容器中的ObjectMapper为Mock实例 private ObjectMapper controllerObjectMapper; @Autowired private ObjectMapper testObjectMapper; // 单独注入真实实例用于测试序列化 @BeforeEach void setUp() throws JsonProcessingException { // 配置Mock的writeValueAsString方法,用真实逻辑返回序列化结果 when(controllerObjectMapper.writeValueAsString(any(Object.class))) .thenAnswer(invocation -> new ObjectMapper().writeValueAsString(invocation.getArgument(0))); } @Test void testCreateItem() throws Exception { Item testItem = new Item("test-item", 100); mockMvc.perform(post("/api/items") .contentType(MediaType.APPLICATION_JSON) .content(testObjectMapper.writeValueAsString(testItem))) .andExpect(status().isOk()); } }
3. 常见错误排查
- 不Mock时控制器报错:通常是控制器未正确注入
ObjectMapper(比如自行new ObjectMapper()或Spring容器中无ObjectMapperBean),确保用构造注入或@Autowired获取Spring管理的实例即可解决。 - Mock时测试报错:大多是Mock的
ObjectMapper未配置writeValueAsString的行为,导致调用时返回null或抛出Stubbing异常,按上述方式为Mock实例设置响应逻辑即可修复。
内容的提问来源于stack exchange,提问作者Prajwala P
相关产品推荐
相关产品推荐

