You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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容器中无ObjectMapper Bean),确保用构造注入或@Autowired获取Spring管理的实例即可解决。
  • Mock时测试报错:大多是Mock的ObjectMapper未配置writeValueAsString的行为,导致调用时返回null或抛出Stubbing异常,按上述方式为Mock实例设置响应逻辑即可修复。

内容的提问来源于stack exchange,提问作者Prajwala P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:35:20