Spring Boot测试中Mock MDC数据遇Mockito方法调用异常问题
解决Mockito Mock MDC静态方法报错的问题
你遇到的MissingMethodInvocationException是因为MDC的get方法是静态方法,普通的Mockito mock方式没法处理静态方法调用,必须用Mockito的静态Mock特性来解决。
错误原因
MDC是SLF4J提供的静态工具类,所有方法都是静态的。你原来的mock(MDC.class)只是创建了一个MDC的实例mock,但实际代码中调用的是MDC.get("correlation-id")这种静态方法,和你mock的实例没关系,所以Mockito会认为你没有调用mock对象的方法,抛出这个错误。
解决方案
1. 先确保依赖正确
需要引入Mockito的inline依赖(支持静态mock),如果是Maven项目,在pom.xml中添加:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>4.0.0</version> <!-- 或更高兼容版本 --> <scope>test</scope> </dependency>
如果是Gradle项目:
testImplementation 'org.mockito:mockito-inline:4.0.0'
2. 修改测试代码(两种方式可选)
方式一:使用@MockStatic注解
@ExtendWith(MockitoExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = TestApp.class) public class Test { private MockMvc restMvc; @MockStatic(MDC.class) // 静态mock MDC类 private MDC mdcMock; @Autowired private TestController testController; // 注入待测试的控制器 @Before public void setUp() { this.restMvc = MockMvcBuilders.standaloneSetup(testController).build(); } @Test public void testMe() throws Exception { when(MDC.get("correlation-id")).thenReturn("1234"); // 初始化请求参数和header restMvc.perform(get("/assignments") .headers(headers) .params(reqParams) .principal(token) .accept(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(status().is2xxSuccessful()); } }
方式二:编程式静态Mock(手动管理生命周期)
如果不想用注解,也可以用Mockito.mockStatic的返回值管理mock生命周期,推荐用try-with-resources自动关闭:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = TestApp.class) public class Test { private MockMvc restMvc; @Autowired private TestController testController; @Before public void setUp() { this.restMvc = MockMvcBuilders.standaloneSetup(testController).build(); } @Test public void testMe() throws Exception { // try-with-resources自动关闭静态mock,避免影响其他测试 try (MockedStatic<MDC> mockedMDC = Mockito.mockStatic(MDC.class)) { mockedMDC.when(() -> MDC.get("correlation-id")).thenReturn("1234"); // 初始化请求参数和header restMvc.perform(get("/assignments") .headers(headers) .params(reqParams) .principal(token) .accept(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(status().is2xxSuccessful()); } } }
注意点
- 静态mock会影响测试类的全局状态,用try-with-resources或者
@MockStatic配合MockitoExtension可以自动隔离不同测试方法的静态mock。 - 如果你的Spring Boot版本较老,需要调整Mockito版本确保兼容性。
内容的提问来源于stack exchange,提问作者Harshana
相关产品推荐
相关产品推荐

