Mockito测试报错Missing method invocation:静态类方法Stub问题求助
解决Mockito静态类Mock报错问题
你遇到的问题核心是Mockito默认不支持直接mock静态类的方法,而你尝试mockValidation的实例去stub静态方法的方式是完全无效的,这才导致了MissingMethodInvocationException。让我一步步帮你修正测试用例:
错误原因分析
- 不该Mock Controller本身:你之前的代码里
Mockito.mock(SampleController.class)然后stub它的abc方法,这相当于跳过了Controller的真实逻辑,只是在模拟方法返回,完全失去了测试的意义。我们应该测试真实的Controller实例,只是把它依赖的外部服务(比如service)和对象(比如HttpServletRequest)mock掉。 - 静态类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
相关产品推荐
相关产品推荐

