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

Mockito测试报错Missing method invocation:静态类方法Stub问题求助

解决Mockito静态类Mock报错问题

你遇到的问题核心是Mockito默认不支持直接mock静态类的方法,而你尝试mockValidation的实例去stub静态方法的方式是完全无效的,这才导致了MissingMethodInvocationException。让我一步步帮你修正测试用例:

错误原因分析

  1. 不该Mock Controller本身:你之前的代码里Mockito.mock(SampleController.class)然后stub它的abc方法,这相当于跳过了Controller的真实逻辑,只是在模拟方法返回,完全失去了测试的意义。我们应该测试真实的Controller实例,只是把它依赖的外部服务(比如service)和对象(比如HttpServletRequest)mock掉。
  2. 静态类Mock方式错误:Validation是外部Jar的静态类,静态方法属于类本身而非实例。你创建Validation的mock实例后调用静态方法,本质上还是调用真实的静态方法,所以when(validation.numberValiadtion("467"))并不是mock对象的方法调用,这就是报错的直接原因。

解决方案(使用Mockito 3.4.0+的静态Mock功能)

从Mockito 3.4.0版本开始,官方支持了静态类的Mock,不需要依赖PowerMock。以下是修正后的完整测试代码:

@RunWith(MockitoJUnitRunner.Silent.class)
public class ApplicationTest {
    // Mock Controller依赖的Service
    @Mock
    AbcService service;
    // Mock HttpServletRequest对象
    @Mock
    HttpServletRequest httpReq;

    // 实例化真实的Controller,并自动注入上面的Mock依赖
    @InjectMocks
    private SampleController restController;

    @Test
    public void abcSuccess() throws Exception {
        // 准备测试数据
        RequestData req = new RequestData();
        req.setNumber("467"); // 设置有效的数字
        ResponseData expectedResp = new ResponseData();

        // 静态Mock Validation类,使用try-with-resources自动关闭mock
        try (MockedStatic<Validation> mockedValidation = Mockito.mockStatic(Validation.class)) {
            // Stub静态方法:当调用numberValiadtion传入有效数字时返回true
            mockedValidation.when(() -> Validation.numberValiadtion(req.getNumber())).thenReturn(true);
            // Stub Service的方法:当调用getScheduleData返回预设的ResponseData
            Mockito.when(service.getScheduleData(req)).thenReturn(expectedResp);

            // 调用真实的Controller方法
            ResponseData actualResp = restController.abc(req, httpReq);

            // 验证结果正确性
            Assert.assertEquals(expectedResp, actualResp);
            // 验证静态方法被正确调用
            mockedValidation.verify(() -> Validation.numberValiadtion(req.getNumber()));
            // 验证Service方法被正确调用
            Mockito.verify(service).getScheduleData(req);
            // 验证request的setAttribute方法被正确调用
            Mockito.verify(httpReq).setAttribute("req", req);
        }
    }

    // 补充测试失败场景:数字无效时抛出异常
    @Test(expected = NumberNotFoundException.class)
    public void abcInvalidNumberThrowsException() throws Exception {
        RequestData req = new RequestData();
        req.setNumber("invalid-123"); // 设置无效数字

        try (MockedStatic<Validation> mockedValidation = Mockito.mockStatic(Validation.class)) {
            // Stub静态方法返回false
            mockedValidation.when(() -> Validation.numberValiadtion(req.getNumber())).thenReturn(false);

            // 调用方法,预期抛出NumberNotFoundException
            restController.abc(req, httpReq);
        }
    }
}

关键要点说明

  • @InjectMocks的作用:自动将标注了@Mock的对象注入到真实的Controller实例中,不需要手动写setter或者构造方法注入,简化测试代码。
  • MockedStatic的使用:通过Mockito.mockStatic(Validation.class)创建静态类的mock,try-with-resources语法会在代码块结束后自动关闭mock,避免影响其他测试用例的执行。
  • 验证逻辑完整性:不仅要测试成功场景,还要测试失败场景(比如无效数字抛出异常),确保Controller的所有分支都被覆盖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:52:44