JUnit 5控制器单元测试中Jackson ObjectMapper为null如何解决
问题原因
你当前的测试写法存在两个核心问题:
@ExtendWith(MockitoExtension.class)属于纯Mockito单元测试环境,不会启动Spring容器,@MockBean是Spring Boot Test专属注解,在当前环境下完全不生效。@Mock修饰的ObjectMapper是Mockito生成的空代理对象,没有手动配置打桩规则时,调用writeValueAsString方法会默认返回null,不会执行真实的JSON序列化逻辑。
实际上你用到的ObjectMapper只是测试代码里用来构造请求参数的工具类,既不需要注入到Controller中,也不需要做Mock处理,直接使用真实实例即可。
修正方案
直接在测试类中手动实例化真实的ObjectMapper对象,同时将不生效的@MockBean替换为Mockito原生的@Mock注解即可,完全不需要加载Spring上下文。
修正后的完整测试代码如下:
@ExtendWith(MockitoExtension.class) public class CarControllerTest { private MockMvc mockMvc; // 直接实例化真实序列化工具,无需Mock或Spring注入 private final ObjectMapper objectMapper = new ObjectMapper(); @InjectMocks private CarController carController; // 纯Mockito环境使用原生@Mock模拟业务依赖 @Mock private CarParts carParts; @BeforeEach public void before() { mockMvc = MockMvcBuilders.standaloneSetup(carController).build(); } @Test @DisplayName("Car Controller Test") public void carControllerTest() { try { CarCustomRequest carCustomRequest = buildRequest(); ResultActions resultActions = mockMvc.perform(post("/custom/endpoint") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(carCustomRequest))); MvcResult mvcResult = resultActions.andExpect(status().isOk()).andReturn(); assertTrue(mvcResult.getResponse().getStatus() == 200); } catch (Exception e) { fail("Error testing /custom/endpoint"); } } // 保留原有构造测试请求对象的逻辑 private CarCustomRequest buildRequest() { return new CarCustomRequest(); } }
补充说明
- 如果你的项目中ObjectMapper有自定义配置(比如支持Java8时间类型、命名字段转换策略等),实例化时直接追加对应配置即可,示例:
private final ObjectMapper objectMapper = new ObjectMapper() .registerModule(new JavaTimeModule()) .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
- 这种基于
MockMvcBuilders.standaloneSetup的测试是轻量级单元测试,不需要启动Spring容器,执行速度快,完全满足你不使用@SpringBootTest和@AutoConfigureMockMvc的要求。 - 单元测试中不要Mock你需要执行真实逻辑的工具类,类似ObjectMapper这种通用序列化工具,直接使用真实实例远比手动打桩简单可靠,Mock只适合用来模拟当前测试逻辑中不需要关注内部实现、仅需要指定返回结果的业务依赖(比如当前测试中的CarParts组件)。
内容的提问来源于stack exchange,提问作者BugsOverflow
相关产品推荐
相关产品推荐

