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

如何在@InjectMocks注入前完成@Mock对象的方法预配置?

解决方案

核心问题是Mockito的初始化逻辑中,@InjectMocks标注类的实例化会在@BeforeEach回调之前执行,因此在@BeforeEach中对@Mock对象打桩时,ClassB的构造方法已经执行完成,final字段stuff已经被赋值为null。


方案1:纯Mockito环境,最小化手动代码

放弃@InjectMocks注解,手动在实例初始化块中完成打桩和类实例化,仅需1行手动创建代码,符合尽量减少手动逻辑的要求:

@ExtendWith(MockitoExtension.class)
class MyTest{
    @Mock
    private ClassA classA;

    private ClassB classB;
    // 实例初始化块,在测试类实例化后、生命周期回调前执行
    {
        // 先打桩再实例化ClassB
        Mockito.lenient().when(classA.getStuff()).thenReturn("预期返回值");
        classB = new ClassB(classA);
    }

    //Tests omitted
}

这里添加lenient()是为了避免Mockito报未使用的打桩警告,如果你所有测试用例都会触发getStuff调用可以去掉


方案2:Spring Boot测试环境,完全注解实现

如果使用Spring Boot测试框架,可以用@MockBean+@BeforeEach实现完全注解化配置,不需要手动创建ClassB实例:

@SpringBootTest
class MyTest{
    @MockBean
    private ClassA classA;

    @Autowired
    private ClassB classB;

    @BeforeEach
    void stub(){
        // Spring上下文初始化时会先处理@MockBean的打桩,再初始化ClassB,因此打桩会生效
        Mockito.when(classA.getStuff()).thenReturn("预期返回值");
    }

    //Tests omitted
}

方案3:纯注解无手动代码实现(需要自定义Answer类)

如果完全不想写手动创建逻辑,可以自定义Answer类,通过@Mock注解的answer参数指定默认返回逻辑:

// 自定义Answer类,处理getStuff方法的返回
public class ClassAStubAnswer implements Answer<Object> {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        if (invocation.getMethod().getName().equals("getStuff")) {
            return "预期返回值";
        }
        // 其他方法返回默认值
        return Mockito.RETURNS_DEFAULTS.answer(invocation);
    }
}

测试类代码:

@ExtendWith(MockitoExtension.class)
class MyTest{
    // 通过注解指定Answer,mock初始化时就自带打桩逻辑
    @Mock(answer = ClassAStubAnswer.class)
    private ClassA classA;

    @InjectMocks
    private ClassB classB;

    //Tests omitted
}

该方案完全不需要手动编写对象创建逻辑,所有配置均通过注解实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:15:04