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

使用Mockito Mock接口时触发NullPointerException问题排查

问题分析与解决方案

核心问题1:@Autowired MockMvc 空指针

你用@WebMvcTest(IMnJobManager.class)时,Spring Boot的@WebMvcTest注解需要传入控制器的实现类(也就是CMnJobManager),而非接口IMnJobManager。这个注解的作用是加载指定控制器到测试上下文,传接口的话,容器找不到对应的控制器实例,无法创建MockMvc,导致@Autowired拿到null,调用mockMvc.perform()时触发空指针。

核心问题2:standaloneSetup 导致404

你用MockMvcBuilders.standaloneSetup(allWorkFlows).build()时,传入的是IMnAllWorkFlows的Mock对象,而非控制器CMnJobManager的实例。standaloneSetup需要传入处理请求的控制器实例,否则Spring找不到对应的请求映射,返回404。就算传入控制器,也要把Mock依赖注入进去,不然控制器里的依赖还是null,无法正常工作。

正确的测试写法

方式1:用@WebMvcTest + @MockBean(推荐)

利用Spring测试上下文自动注入依赖,写法更简洁:

@WebMvcTest(CMnJobManager.class)
public class CMnJobManagerTest {

    @Autowired
    private MockMvc mockMvc;

    // 用@MockBean为控制器的所有依赖创建Mock,Spring会自动注入到控制器中
    @MockBean
    private IMnAllWorkFlows allWorkFlows;
    @MockBean
    private IMnWorkflowService workflowService;
    @MockBean
    private IMnTemporalServiceClient temporalServiceClient;
    @MockBean
    private IMnWorkflowHistoryService workflowHistoryService;
    @MockBean
    private IMnSearchAttributeService searchAttributeService;
    @MockBean
    private IMnS3Tenant s3Tenant;
    @MockBean
    private HttpServletRequest request;
    @MockBean
    private CMnCustomMetricService customMetricService;

    @Test
    public void testExample() throws Exception {
        // 配置Mock方法的返回值
        Mockito.when(allWorkFlows.getAllTenants())
               .thenReturn(Arrays.asList("modn-ops"));

        mockMvc.perform(get("/v1/tenant"))
               .andExpect(status().isOk())
               // 接口返回的是List,用containsString匹配,或用jsonPath断言更准确
               .andExpect(content().string(org.hamcrest.Matchers.containsString("modn-ops")))
               .andDo(print());
    }
}

方式2:用standaloneSetup手动初始化

如果不想依赖Spring上下文,手动构建控制器和MockMvc:

public class CMnJobManagerTest {

    @Test
    public void testExample() throws Exception {
        // 手动创建所有依赖的Mock
        IMnAllWorkFlows allWorkFlows = Mockito.mock(IMnAllWorkFlows.class);
        IMnWorkflowService workflowService = Mockito.mock(IMnWorkflowService.class);
        IMnTemporalServiceClient temporalServiceClient = Mockito.mock(IMnTemporalServiceClient.class);
        IMnWorkflowHistoryService workflowHistoryService = Mockito.mock(IMnWorkflowHistoryService.class);
        IMnSearchAttributeService searchAttributeService = Mockito.mock(IMnSearchAttributeService.class);
        IMnS3Tenant s3Tenant = Mockito.mock(IMnS3Tenant.class);
        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
        CMnCustomMetricService customMetricService = Mockito.mock(CMnCustomMetricService.class);

        // 创建控制器实例,传入所有Mock依赖
        CMnJobManager controller = new CMnJobManager(allWorkFlows, workflowService, temporalServiceClient,
                workflowHistoryService, searchAttributeService, s3Tenant);
        // 手动注入@Autowired字段(构造器未处理的依赖)
        controller.request = request;
        controller.customMetricService = customMetricService;

        // 初始化MockMvc,传入控制器实例
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();

        // 配置Mock方法
        Mockito.when(allWorkFlows.getAllTenants()).thenReturn(Arrays.asList("modn-ops"));

        mockMvc.perform(get("/v1/tenant"))
               .andExpect(status().isOk())
               .andExpect(content().string(org.hamcrest.Matchers.containsString("modn-ops")))
               .andDo(print());
    }
}

关键注意点

  • @WebMvcTest必须传控制器实现类,不能传接口
  • 手动创建的Mock必须注入到控制器中,否则控制器用的是真实依赖(或null),Mock逻辑不会生效
  • 如果接口返回集合,不要直接用content().string("modn-ops")断言,应该用jsonPath或containsString匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:57:06