如何用Mockito模拟类内部生成对象的行为(无需传Mock对象)
仅用Mockito测试类内部创建的依赖对象
针对你遇到的类内部自行创建依赖对象、需要用Mockito模拟其行为的场景,这里提供两种纯Mockito的实现方案,无需修改业务代码、不用PowerMockito:
方案1:使用Spy对象Stub私有初始化方法
通过创建MyClass的Spy对象(部分模拟真实实例),让私有初始化方法setupClient()返回预先mock好的Client实例,从而替换掉真实的依赖对象。
业务类代码(补充完整)
public class MyClass { private Client someClient; public MyClass() { this.someClient = setupClient(); } private Client setupClient() { // 真实的Client初始化逻辑 return new Client(); } public void methodIWantToTest(String requestString) { this.someClient.makeApiCall(requestString); // 其他业务逻辑 } } class Client { public void makeApiCall(String request) { // 真实API调用逻辑 } }
测试类代码
import org.junit.Test; import org.mockito.Mockito; public class MyClassTest { @Test public void testMethodIWantToTest() { // 1. 生成Client的Mock实例 Client mockClient = Mockito.mock(Client.class); // 2. 创建MyClass的Spy对象,保留真实类的大部分行为 MyClass testInstance = Mockito.spy(new MyClass()); // 3. Stub私有方法setupClient,使其返回Mock的Client // 注意:私有方法必须用doReturn语法,不能用when(...).thenReturn(...) Mockito.doReturn(mockClient).when(testInstance).setupClient(); // 4. 定义Mock对象的行为:调用makeApiCall时什么都不做 Mockito.doNothing().when(mockClient).makeApiCall(Mockito.anyString()); // 5. 执行待测试方法 testInstance.methodIWantToTest("test_request"); // 6. 验证Mock对象的方法是否被正确调用 Mockito.verify(mockClient).makeApiCall("test_request"); } }
方案2:通过反射直接替换私有字段
如果Spy方式因为构造方法执行时会先调用真实的setupClient()导致问题,可以直接用Mockito内置的反射工具替换someClient私有字段,跳过初始化逻辑直接注入Mock对象。
测试类代码
import org.junit.Test; import org.mockito.Mockito; import org.mockito.internal.util.reflection.FieldSetter; public class MyClassTest { @Test public void testMethodIWantToTest() throws NoSuchFieldException { // 1. 生成Client的Mock实例 Client mockClient = Mockito.mock(Client.class); // 2. 创建真实的MyClass实例 MyClass testInstance = new MyClass(); // 3. 用Mockito的FieldSetter替换私有字段someClient为Mock对象 FieldSetter.setField(testInstance, MyClass.class.getDeclaredField("someClient"), mockClient); // 4. 定义Mock行为并执行测试 Mockito.doNothing().when(mockClient).makeApiCall(Mockito.anyString()); testInstance.methodIWantToTest("test_request"); // 5. 验证方法调用 Mockito.verify(mockClient).makeApiCall("test_request"); } }
两种方案均基于纯Mockito实现,不需要改动业务类的构造方式或依赖注入逻辑,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Jeremy Fisher
相关产品推荐
相关产品推荐

