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

如何在@InjectMocks注入前Stub @Mock对象方法适配构造函数初始化?

问题

类A的构造函数会从注入的对象B中获取属性,存入变量时还用了requireNonNull做非空校验。测试时需要在构造函数注入前Stub Mock对象B的方法,但发现@InjectMocks会在@BeforeEach之前完成注入,导致Mock方法返回null触发非空校验,测试根本跑不起来。这种场景下还能使用@Mock和@InjectMocks吗?

对应的代码示例:

class A {
    String c;

    A(B b) {
        c = requireNonNull(b.getC());
    }
}

@ExtendWith(MockitoExtension.class)
class ATest {
    @Mock B b;
    @InjectMocks A a;

    @BeforeEach void setUp() {
        when(b.getC()).thenReturn("");
    }

    @Test void test() {}
}
解决方案

可以用@Mock,但不适合直接用@InjectMocks——因为@InjectMocks的初始化时机确实早于@BeforeEach,没法提前Stub依赖的方法。给你两种靠谱的调整方式:

方式一:手动创建A实例

直接放弃@InjectMocks,在@BeforeEach里先把Mock对象的方法Stub好,再手动new出A的实例。这样就能保证构造函数执行时,Mock的方法已经能返回预期值:

@ExtendWith(MockitoExtension.class)
class ATest {
    @Mock B b;
    A a; // 去掉@InjectMocks注解

    @BeforeEach void setUp() {
        when(b.getC()).thenReturn("");
        a = new A(b); // 手动初始化A
    }

    @Test void test() {}
}

方式二:用@BeforeAll提前Stub(仅限无状态Mock)

如果Mock对象B是无状态的,不会在测试用例之间被修改,可以把Stub逻辑放到@BeforeAll里——注意这个注解修饰的方法必须是static的,对应的Mock对象也要加static:

@ExtendWith(MockitoExtension.class)
class ATest {
    @Mock static B b; // 必须加static
    @InjectMocks A a;

    @BeforeAll static void setUp() { // 方法必须是static
        when(b.getC()).thenReturn("");
    }

    @Test void test() {}
}

不过更推荐方式一,因为@BeforeAll的static Mock容易在测试用例之间造成状态污染,手动初始化的方式不仅灵活可控,逻辑也更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:55:13