如何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
相关产品推荐
相关产品推荐

