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

使用@InjectMocks注入前初始化Mock对象内部(Foo2)的问题求助

解决Mockito中@InjectMocks注入前初始化Foo2内部结构的问题

我完全懂你的痛点:你不想把Foo2完全Mock掉,而是希望它内部的某个对象用真实实例(基于ObjectA初始化),这样调用Foo2的方法时,这个内部对象能返回你要的结果,但用@InjectMocks的时候总是搞不定初始化时机对吧?

下面给你两个靠谱的解决方案,根据你的场景选就行:

方案1:用@Spy替代@Mock + 手动初始化内部对象

如果Foo2的内部对象可以通过Setter或者包私有方式访问,这个方案最方便:

  • 别再给Foo2加@Mock了,换成@Spy。@Spy的好处是默认会走Foo2的真实方法逻辑,只有你明确Stub的方法才会被Mock,完美契合你要保留部分真实逻辑的需求
  • 在测试类的初始化方法(JUnit4用@Before,JUnit5用@BeforeEach)里,手动用ObjectA创建真实的内部对象,然后赋值给Foo2

举个代码例子:

public class YourTest {
    @Spy
    private Foo2 foo2; // 用Spy保留真实方法
    
    @InjectMocks
    private YourServiceUnderTest service; // 依赖Foo2的待测试类
    
    @BeforeEach
    void setUp() {
        // 先创建你需要的ObjectA真实实例
        ObjectA realObjectA = new ObjectA("你要的参数值");
        // 假设Foo2内部的对象是bar,用ObjectA初始化它
        Bar realBar = new Bar(realObjectA);
        // 如果有Setter直接调用,没有的话用反射
        foo2.setBar(realBar);
        
        // 要是你需要Stub Foo2的某些方法,照样可以写
        // when(foo2.someMethod()).thenReturn("自定义返回");
    }
    
    @Test
    void testYourBusinessLogic() {
        service.execute();
        // 此时Foo2的bar是真实初始化的,会按ObjectA的参数返回预期结果
        // 这里写你的断言逻辑...
    }
}

方案2:手动构造Foo2实例后交给@InjectMocks

如果Foo2的内部对象必须在构造时传入(比如没有Setter),那直接手动创建Foo2的真实实例就行:

  • 测试类里的Foo2字段不要加任何Mockito注解
  • 在初始化方法里,先创建ObjectA,再用它构造Foo2的内部对象,最后实例化Foo2
  • @InjectMocks会自动把这个手动创建的Foo2注入到你的待测试类里

代码示例:

public class YourTest {
    private Foo2 foo2; // 不标注Mock/Spy,手动初始化
    
    @InjectMocks
    private YourServiceUnderTest service;
    
    @BeforeEach
    void setUp() {
        // 一步一步构造真实依赖链
        ObjectA realObjectA = new ObjectA("预期参数");
        Bar realBar = new Bar(realObjectA);
        foo2 = new Foo2(realBar); // 完全真实的Foo2实例
    }
    
    @Test
    void testYourBusinessLogic() {
        service.execute();
        // Foo2内部的bar已经基于ObjectA初始化,能返回你要的结果
    }
}

踩坑提醒

  • 之前用@Mock标注Foo2的话,Mockito会生成一个“空壳”Mock对象,它的所有内部字段都是null,调用方法时不会走真实逻辑,这就是你之前代码跑不通的核心原因
  • 如果Foo2的内部对象是私有字段且没有Setter,可以用Mockito自带的Whitebox.setInternalState()来强制设置,比如:
Whitebox.setInternalState(foo2, "bar", realBar);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:20:04