You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:12:58