如何使用Mockito模拟静态main方法内创建的ApplicationContext和Mapper对象行为
解答
可以实现,需要使用Mockito 3.4及以上版本配套的mockito-inline依赖(默认的mockito-core不支持构造方法、静态方法的Mock能力)。
实现思路
你可以通过MockAnnotationConfigApplicationContext的构造行为,让测试过程中创建的上下文对象是Mock对象,再自定义Mock上下文的getBean方法返回你提前Mock好的SomeMapper实例,就能完全脱离真实数据库完成测试。
示例测试代码
import org.junit.jupiter.api.Test; import org.mockito.MockedConstruction; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import static org.mockito.Mockito.*; public class MainTest { @Test public void testMainMethod() { // 1. 提前Mock SomeMapper实例,自定义getData方法的行为 SomeMapper mockMapper = mock(SomeMapper.class); when(mockMapper.getData()).thenReturn("模拟的测试数据"); // 2. Mock AnnotationConfigApplicationContext的构造方法 try (MockedConstruction<AnnotationConfigApplicationContext> mockedCxtConstruction = mockConstruction(AnnotationConfigApplicationContext.class, (mockCxt, context) -> { // 定义Mock上下文的getBean方法返回准备好的mockMapper when(mockCxt.getBean(SomeMapper.class)).thenReturn(mockMapper); })) { // 3. 直接调用main方法执行测试 Main.main(new String[]{}); // 4. 可选:验证方法调用是否符合预期 verify(mockMapper, times(1)).getData(); } } }
额外说明
- 如果你可以调整原有业务代码,更推荐把依赖获取逻辑抽离,避免在静态方法里硬编码初始化Spring上下文,后续测试和维护都会更简单。
mockConstruction、mockStatic这类能力都是作用域绑定的,放在try-with-resources代码块内只会对当前测试逻辑生效,不会影响其他测试用例的执行。
内容的提问来源于stack exchange,提问作者Akshay Mishra
相关产品推荐
相关产品推荐

