如何使用Mockito对私有方法内声明的类实例进行Mock
私有方法内部硬编码实例的Mock解决方案
核心思路:由于你要测试的私有方法内部直接通过
new ClassName()硬编码生成实例,普通Mock框架无法拦截实例化过程,需要搭配具备构造函数拦截能力的Mock工具,配合现有WhiteBox API调用私有方法即可实现需求。
方案1:PowerMock + WhiteBox(兼容JUnit4)
- 首先添加PowerMock相关依赖(以Maven为例):
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency>
- 测试类添加必要注解:
@RunWith(PowerMockRunner.class) // 此处填写你私有方法所在的类、以及要拦截构造的ClassName @PrepareForTest({TargetClass.class, ClassName.class}) public class TargetClassTest { }
- 测试方法逻辑:
@Test public void testGetFunctReturn() throws Exception { // 1. 初始化待测试类实例 TargetClass testInstance = new TargetClass(); // 2. Mock ClassName实例,并预设getMap方法返回值 ClassName mockClassName = Mockito.mock(ClassName.class); Map mockMap = new HashMap<>(); // 自行填充map测试数据 mockMap.put("k1", "v1"); Mockito.when(mockClassName.getMap()).thenReturn(mockMap); // 3. 拦截无参构造方法,所有new ClassName()调用都会返回上面的mock实例 PowerMockito.whenNew(ClassName.class).withNoArguments().thenReturn(mockClassName); // 4. 用WhiteBox调用私有方法,此时内部生成的就是你Mock的实例 Object result = Whitebox.invokeMethod(testInstance, "getFunctReturn"); // 5. 自定义断言逻辑 Assert.assertNotNull(result); }
方案2:Mockito原生构造Mock(兼容JUnit5,无需PowerMock)
如果使用Mockito 3.5+版本,可以用原生mockConstruction方法拦截构造调用,无需引入PowerMock:
@Test public void testGetFunctReturn() { TargetClass testInstance = new TargetClass(); Map mockMap = new HashMap<>(); mockMap.put("k1", "v1"); // 拦截ClassName的所有构造调用,统一预设返回值 try (MockedConstruction<ClassName> mockedConstruction = Mockito.mockConstruction(ClassName.class, (mock, context) -> Mockito.when(mock.getMap()).thenReturn(mockMap))) { // 调用私有方法,内部new的ClassName全为Mock实例 Object result = Whitebox.invokeMethod(testInstance, "getFunctReturn"); // 断言逻辑 Assert.assertNotNull(result); // 可选:验证构造方法调用次数 Assert.assertEquals(1, mockedConstruction.constructed().size()); } }
注意:如果使用的WhiteBox是Spring提供的
ReflectionTestUtils,只需把调用私有方法的代码替换为ReflectionTestUtils.invokeMethod(testInstance, "getFunctReturn")即可,Mock逻辑完全通用。
内容的提问来源于stack exchange,提问作者TechP88
相关产品推荐
相关产品推荐

