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

如何Mock Java私有方法中创建的ObjectNeeded2Mock以测试公共方法?

如何Mock私有方法中直接创建的ObjectNeeded2Mock对象

方案一:用PowerMock拦截构造方法(不用改原代码)

因为原代码里ObjectNeeded2Mock是在私有方法里直接new出来的,常规Mockito搞不定这种硬编码的对象创建,得用PowerMock来拦截构造方法:

  1. 先引入PowerMock的依赖(比如JUnit4环境下,需要powermock-module-junit4和powermock-api-mockito2这两个包)
  2. 测试类上加两个注解:
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(parentClass.class) // 指定要处理的类,因为它里面new了目标对象
    
  3. 测试方法里这么写:
    @Test
    public void testMethod1() throws Exception {
        // 先创建ObjectNeeded2Mock的mock实例
        ObjectNeeded2Mock mockObj = Mockito.mock(ObjectNeeded2Mock.class);
        // 拦截parentClass里new ObjectNeeded2Mock()的操作,返回我们的mock对象
        PowerMockito.whenNew(ObjectNeeded2Mock.class).withNoArguments().thenReturn(mockObj);
        
        // 给mock对象设置预期行为,比如调用某个方法返回指定值
        Mockito.when(mockObj.someMethod()).thenReturn("你要的结果");
        
        // 实例化parentClass并调用方法
        parentClass parent = new parentClass();
        String result = parent.method1("测试参数");
        
        // 验证结果和mock对象的调用情况
        Assert.assertEquals("预期返回值", result);
        Mockito.verify(mockObj).someMethod();
    }
    

注意:这种方法适合没法改原代码的场景,但PowerMock会修改类加载机制,可能带来一些额外问题,比如和其他测试框架的兼容性。

方案二:重构原代码(更推荐,测试友好)

硬编码new对象本身就不利于测试,最好的办法是把对象创建的逻辑抽出来,让依赖可以注入:

修改原代码:

给parentClass加一个带参数的构造方法,用来传入对象的创建逻辑,同时保留原无参构造保证兼容性:

class parentClass {
    private final Supplier<ObjectNeeded2Mock> objCreator;
    
    // 原无参构造,保持原有功能不变
    public parentClass() {
        this(() -> new ObjectNeeded2Mock());
    }
    
    // 测试用的构造方法,传入自定义的对象创建逻辑
    public parentClass(Supplier<ObjectNeeded2Mock> objCreator) {
        this.objCreator = objCreator;
    }
    
    public String method1(String... arguments){
        Obj obj1 = privateMethod(arguments[0]);
        return "处理结果";
    }
    
    private Obj privateMethod(String argument){
        // 用Supplier创建对象,而不是直接new
        ObjectNeeded2Mock obj = objCreator.get();
        // 原来的业务逻辑
        return new Obj();
    }
}

测试代码:

这时候用常规Mockito就能搞定,不用额外框架:

@Test
public void testMethod1() {
    // 创建mock对象
    ObjectNeeded2Mock mockObj = Mockito.mock(ObjectNeeded2Mock.class);
    // 设置mock的预期行为
    Mockito.when(mockObj.someMethod()).thenReturn("预期值");
    
    // 实例化parentClass时,传入返回mock对象的Supplier
    parentClass parent = new parentClass(() -> mockObj);
    
    // 调用方法并获取结果
    String result = parent.method1("测试参数");
    
    // 验证结果和mock的调用
    Assert.assertEquals("预期返回结果", result);
    Mockito.verify(mockObj).someMethod();
}

这种方式让代码结构更清晰,符合依赖倒置原则,后续维护起来也更方便,是长期来看更优的选择。

内容的提问来源于stack exchange,提问作者Jacobo Geada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:50:26