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

Spring Boot 1.5.9中如何Mock自定义Jackson反序列化器响应

解决@WebMvcTest中Mock自定义JsonDeserializer的问题

我之前也碰到过完全一样的坑——用@WebMvcTest测试控制器时,自定义的JsonDeserializer总是被直接实例化,Mock根本没生效,最后还抛出了NPE。核心原因确实像你推测的那样:默认情况下,Jackson会直接new你在@JsonDeserializer(using = ...)里指定的类,这个实例不在Spring的ApplicationContext管理范围内,所以Spring的Mock机制(比如@MockBean)根本触达不到它。

不用急着切换到@SpringBootTest(毕竟加载完整上下文会慢很多),这里有两种可行的解决方案:

方案一:把反序列化器转为Spring Bean,让Jackson从容器获取实例

这是更优雅的长期方案,能让反序列化器享受Spring的依赖注入和管理:

  1. 给你的自定义反序列化器加上@Component注解,把它变成Spring Bean:
@Component
public class MyCustomDeserializer extends JsonDeserializer<YourTargetType> {
    // 原来的deserialize方法逻辑
}
  1. 修改实体类上的@JsonDeserializer注解,改用usingProvider来引用Spring容器中的Bean:
public class YourEntity {
    @JsonDeserializer(usingProvider = MyDeserializerProvider.class)
    private YourTargetType yourField;

    // 内部类实现JsonDeserializerProvider
    public static class MyDeserializerProvider extends JsonDeserializerProvider<MyCustomDeserializer> {
        @Autowired
        private MyCustomDeserializer deserializer;

        @Override
        public MyCustomDeserializer getInstance() {
            return deserializer;
        }
    }
}
  1. 现在在@WebMvcTest测试类里,直接用@MockBean就能Mock这个反序列化器了:
@WebMvcTest(YourController.class)
public class YourControllerTest {
    @MockBean
    private MyCustomDeserializer customDeserializer;

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testController() throws Exception {
        // Mock deserialize方法的返回值
        when(customDeserializer.deserialize(any(JsonParser.class), any(DeserializationContext.class)))
                .thenReturn(yourMockedObject);

        // 执行MockMvc请求测试
        mockMvc.perform(post("/your-endpoint")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("{...}"))
                .andExpect(status().isOk());
    }
}

方案二:在测试中自定义Jackson的ObjectMapper,替换反序列化器

如果你不想修改现有代码结构,可以在测试类中手动配置ObjectMapper,把Mock的反序列化器注册进去:

@WebMvcTest(YourController.class)
public class YourControllerTest {
    @Autowired
    private MockMvc mockMvc;

    // 自定义ObjectMapper,注册Mock的反序列化器
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();

        // 创建Mock的反序列化器实例
        MyCustomDeserializer mockDeserializer = Mockito.mock(MyCustomDeserializer.class);
        // Mock返回结果
        when(mockDeserializer.deserialize(any(), any())).thenReturn(yourMockedObject);

        // 把Mock的反序列化器注册到模块中
        module.addDeserializer(YourTargetType.class, mockDeserializer);
        mapper.registerModule(module);

        return mapper;
    }

    // 测试方法...
}

这样@WebMvcTest会使用你自定义的ObjectMapper,而不是默认的,从而让请求解析时使用Mock的反序列化器,避免执行原方法体。

为什么原来的方式不生效?

再重申下核心原因:当你用@JsonDeserializer(using = MyCustomDeserializer.class)时,Jackson会在需要反序列化时直接调用new MyCustomDeserializer()创建实例,这个实例完全脱离Spring容器的管理,所以你用@MockBean创建的Mock实例根本不会被用到,自然会执行原方法体导致NPE。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:38:14