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

如何Mock被Autowired注入的ObjectProvider<MyObject>?

Spring 5.x迁移中ObjectProvider Mock空指针问题解决

问题场景

我正在从Spring 4.x迁移到5.x,按照建议用ObjectProvider包装对象来处理可能返回null的Bean。现有代码结构如下:

ConfigurationClass类

class ConfigurationClass{
  @Autowired
  private ObjectProvider<MyObject> myObject;

  public SomeOtherClass getSomeOtherClass() {
    return new SomeOtherClass(myObject.getIfAvailable());
  }
}

初始测试写法(触发空指针)

class TestSomeOtherClass {
  @Mock
  MyObject myObject;
  
  @InjectMocks
  ConfigurationClass configuration;

  SomeOtherClass someOtherClass;

  public void setup() {
    this.someOtherClass = spy(configuration.getSomeOtherClass());
  }
}

运行测试时,ConfigurationClass中的myObject字段触发空指针异常。

修改后的测试(仍无效)

class TestSomeOtherClass {
  @Mock
  MyObject myObject;

  @Mock
  ObjectProvider<MyObject> myObjectObjectProvider;

  @InjectMocks
  ConfigurationClass configuration;

  SomeOtherClass someOtherClass;

  public void setup() {
    doReturn(myObject).when(myObjectObjectProvider).getIfAvailable();
    this.someOtherClass = spy(configuration.getSomeOtherClass());
  }
}

修改后仍无法成功Mock,请问该如何解决?


解决方案

核心问题是Mockito的@InjectMocks依赖字段名匹配:ConfigurationClass中需要注入的字段名为myObject(类型是ObjectProvider<MyObject>),但测试类里的ObjectProvider实例命名为myObjectObjectProvider,名字不匹配,导致Mockito无法自动注入这个Mock对象,调用getIfAvailable()时自然空指针。

方法一:统一字段名(推荐)

把测试类中的ObjectProvider变量名改成和ConfigurationClass里一致的myObject,同时正确Stub方法:

class TestSomeOtherClass {
  @Mock
  MyObject myObject;

  // 变量名与ConfigurationClass中的字段名保持一致
  @Mock
  ObjectProvider<MyObject> myObject;

  @InjectMocks
  ConfigurationClass configuration;

  SomeOtherClass someOtherClass;

  @Before // JUnit4用@Before,JUnit5用@BeforeEach,确保初始化逻辑提前执行
  public void setup() {
    // Stub getIfAvailable方法,返回预先Mock的MyObject实例
    doReturn(myObject).when(myObject).getIfAvailable();
    this.someOtherClass = spy(configuration.getSomeOtherClass());
  }
}

方法二:手动注入(不修改变量名时用)

如果不想调整变量名,可以通过反射工具手动给ConfigurationClass的字段赋值:

class TestSomeOtherClass {
  @Mock
  MyObject myObject;

  @Mock
  ObjectProvider<MyObject> myObjectObjectProvider;

  @InjectMocks
  ConfigurationClass configuration;

  SomeOtherClass someOtherClass;

  @Before
  public void setup() {
    doReturn(myObject).when(myObjectObjectProvider).getIfAvailable();
    // 手动注入ObjectProvider实例
    ReflectionTestUtils.setField(configuration, "myObject", myObjectObjectProvider);
    this.someOtherClass = spy(configuration.getSomeOtherClass());
  }
}

关键注意点

  • 务必给setup方法加上@Before(JUnit4)或@BeforeEach(JUnit5)注解,否则初始化逻辑不会在测试方法执行前自动运行,Stub的规则也不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:39:18