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

使用@InjectMocks遇构造方法抛异常,如何正确注入Mock?

解决方案

方案1:在测试初始化方法中处理异常并完成注入

不用在字段声明时直接new MyObject(),而是把实例创建放到测试的初始化方法(JUnit 5用@BeforeEach,JUnit 4用@Before)里,方法声明抛出异常或者捕获异常,同时让Mockito完成注入:

public class MyObjectTest {
    @Mock(name = "random")
    Random mockRandom;

    MyObject myObject;

    @BeforeEach
    void setUp() throws Exception {
        // 初始化Mockito注解
        MockitoAnnotations.openMocks(this);
        // 在这里创建实例,方法声明throws Exception解决IDE报错
        myObject = new MyObject();
        // Mockito会自动把mockRandom注入到myObject的private字段中
    }

    // 你的测试方法写在这里
}

这种方法不用修改生产代码,只调整测试类的写法即可,最省事。

方案2:给生产类加一个测试专用的构造函数

在MyObject里新增一个包级私有(或者测试可见)的构造函数,专门用来传入Random实例,原有的无参构造保持不变,业务代码依然用无参构造创建实例,测试用这个专用构造:

首先修改MyObject:

public class MyObject {
    private Random random;
    // 其他属性

    // 业务用的无参构造
    public MyObject() throws Exception {
        this(new Random());
    }

    // 测试专用构造,包级私有,同包测试类可以访问
    MyObject(Random random) throws Exception {
        this.random = random;
        // 把原来构造里的其他逻辑抽成统一的初始化方法,避免代码重复
        init();
    }

    private void init() throws Exception {
        // 原来无参构造里除了初始化random的其他代码
    }
}

然后测试类直接用这个构造传mock:

public class MyObjectTest {
    @Mock
    Random mockRandom;

    MyObject myObject;

    @BeforeEach
    void setUp() throws Exception {
        // 直接传入mock的Random
        myObject = new MyObject(mockRandom);
    }

    // 测试方法
}

这种方式把测试代码和生产代码的耦合降到最低,业务代码完全不受影响,同时测试时能灵活注入mock,是比较优雅的做法。

方案3:手动调用Mockito的注入方法

如果不想改生产代码,也可以手动创建实例后,调用Mockito的injectMocks方法完成注入,同时处理构造异常:

public class MyObjectTest {
    @Mock(name = "random")
    Random mockRandom;

    MyObject myObject;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
        try {
            myObject = new MyObject();
            // 手动触发注入
            Mockito.injectMocks(myObject);
        } catch (Exception e) {
            // 把异常包装成运行时异常抛出,不中断测试流程
            throw new RuntimeException("创建MyObject实例失败", e);
        }
    }

    // 测试方法
}

这个方案和方案1类似,区别在于手动调用注入方法,适合一些特殊场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:15:43