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

Java中如何mock通过new关键字创建的对象?结合示例代码说明

针对Java中new关键字创建对象的Mock方案

以下是基于你提供的代码场景可使用的三种实现方案:

方案1:代码重构(最推荐)

硬编码new对象会导致强耦合,优先推荐通过依赖注入或者工厂模式剥离对象创建逻辑,修改后的业务代码示例:

public class TestClass {
    private final MyObject myobject;
    private SecondObject secondObject;
    // 注入SecondObject工厂
    private final SecondObjectFactory secondObjectFactory;

    // 构造方法注入工厂
    public TestClass(MyObject myObject, SecondObjectFactory secondObjectFactory) {
        this.myObject = myObject;
        this.secondObjectFactory = secondObjectFactory;
    } 

    public void init() {
        secondObject = secondObjectFactory.create(myobject,100,100);
    }

    // 工厂接口定义,也可以用Supplier等函数式接口简化
    public interface SecondObjectFactory {
        SecondObject create(MyObject obj, int arg1, int arg2);
    }
}

测试时直接mock工厂的create方法返回mock的SecondObject即可,测试代码示例:

// 测试代码示例
MyObject mockMyObject = mock(MyObject.class);
SecondObject mockSecondObject = mock(SecondObject.class);
SecondObjectFactory mockFactory = mock(SecondObjectFactory.class);
when(mockFactory.create(mockMyObject, 100, 100)).thenReturn(mockSecondObject);

TestClass testClass = new TestClass(mockMyObject, mockFactory);
testClass.init();
// 后续即可对mockSecondObject进行行为验证

方案2:使用Mockito原生构造Mock(Mockito 3.5.0+版本支持)

如果无法修改原有代码,可以用Mockito提供的mockConstruction方法拦截指定类的构造调用,直接返回mock对象,测试代码示例:

@Test
void testInit() {
    MyObject mockMyObject = mock(MyObject.class);
    TestClass testClass = new TestClass(mockMyObject);
    SecondObject mockSecondObject = mock(SecondObject.class);

    // 拦截SecondObject的所有构造调用,返回mock对象
    try (MockedConstruction<SecondObject> mocked = mockConstruction(SecondObject.class,
            (mock, context) -> {
                // 可以校验构造参数是否符合预期
                assertEquals(mockMyObject, context.arguments().get(0));
                assertEquals(100, context.arguments().get(1));
                assertEquals(100, context.arguments().get(2));
            })) {
        testClass.init();
        // 拿到构造出来的mock对象做验证
        SecondObject constructed = mocked.constructed().get(0);
        // 后续验证逻辑
    }
}

注意:mockConstruction作用域只在try-with-resources代码块内,超出范围就会失效

方案3:使用PowerMock框架(适合低版本Mockito场景)

如果使用的Mockito版本低于3.5.0,可以用PowerMock的whenNew能力拦截构造调用:

  1. 首先引入PowerMock相关依赖
  2. 测试类加上@RunWith(PowerMockRunner.class)和@PrepareForTest(TestClass.class)注解(注意准备的是创建new对象的类,也就是TestClass,不是SecondObject)

测试代码示例:

@RunWith(PowerMockRunner.class)
@PrepareForTest(TestClass.class)
public class TestClassTest {
    @Test
    public void testInit() throws Exception {
        MyObject mockMyObject = mock(MyObject.class);
        SecondObject mockSecondObject = mock(SecondObject.class);
        // 拦截SecondObject的构造调用,参数匹配的话返回mock对象
        PowerMockito.whenNew(SecondObject.class)
                .withArguments(mockMyObject, 100, 100)
                .thenReturn(mockSecondObject);

        TestClass testClass = new TestClass(mockMyObject);
        testClass.init();
        // 后续验证逻辑
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:18:03