Mockito测试中@Autowired对象Mock失败,依赖注入为空求助
解决方案:Mockito @InjectMocks 注入失败导致 Mock 实例为空
我之前也碰到过一模一样的问题,Mockito 的 @InjectMocks 有时候会因为各种小细节导致注入失败,下面是我整理的几个排查和解决办法,你可以逐一尝试:
1. 先确认 Mockito 依赖是否正确
如果你的项目依赖有缺失或者版本不兼容,很容易出现 Mock 注入失效的情况。
Maven 依赖示例(稳定版 4.x):
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency>
Gradle 依赖示例:
testImplementation 'org.mockito:mockito-core:4.11.0' testImplementation 'org.mockito:mockito-junit-jupiter:4.11.0'
2. 手动初始化 Mock 对象(解决 Runner 未生效问题)
有时候 @RunWith(MockitoJUnitRunner.class) 会因为项目里同时引入了 Spring Test 等依赖而失效,这时候手动初始化 Mock 就能解决问题。
修改你的测试类,添加 @Before 方法调用初始化方法:
@RunWith(MockitoJUnitRunner.class) public class DaoBeanTest { @InjectMocks private DaoBean systemUnderTest; @Mock private SomeServiceBean someServiceBean; @Mock private JdbcOperations jdbcTemplate; @Before public void setUp() { // 手动触发所有@Mock和@InjectMocks对象的初始化 MockitoAnnotations.openMocks(this); } @Test public void testId() { Mockito.when(someServiceBean.getEmail(Mockito.anyString())).thenReturn("johndoe@gmail.com"); String result = systemUnderTest.getId("johndoe"); // 这里可以补充断言验证结果,比如: // Assert.assertNotNull(result); } }
3. 检查被测类的继承关系是否有冲突
你的 DaoBean 继承了 SomeBean,如果父类 SomeBean 中也存在同名的 someServiceBean 字段,可能会导致 Mockito 注入混淆。建议检查父类代码,确保没有字段名冲突。
4. 改用构造函数注入(推荐的长期解决方案)
字段注入(@Autowired 标记 private 字段)本身就不利于单元测试,Mockito 依赖反射注入容易出问题。改用构造函数注入不仅能解决测试问题,还能让依赖关系更清晰,符合 Spring 最佳实践。
修改被测类 DaoBean:
@DynamicReadable @Component public class DaoBean extends SomeBean implements Dao { private final JdbcOperations jdbcTemplate; private final SomeServiceBean someServiceBean; // Spring 4.3+ 不需要加@Autowired,会自动识别构造函数注入 public DaoBean(JdbcOperations jdbcTemplate, SomeServiceBean someServiceBean) { this.jdbcTemplate = jdbcTemplate; this.someServiceBean = someServiceBean; } @Override public String getId(String name) { // 注意:原代码里方法声明是void但有return,这是编译错误,记得修正返回值类型 String email = someServiceBean.getEmail(name); return jdbcTemplate.queryForObject("query here", String.class, email); // 示例修正后的查询逻辑 } }
对应的测试类(不需要@InjectMocks了):
@RunWith(MockitoJUnitRunner.class) public class DaoBeanTest { private DaoBean systemUnderTest; @Mock private SomeServiceBean someServiceBean; @Mock private JdbcOperations jdbcTemplate; @Before public void setUp() { // 直接通过构造函数传入Mock对象创建被测实例,完全避免反射注入问题 systemUnderTest = new DaoBean(jdbcTemplate, someServiceBean); } @Test public void testId() { Mockito.when(someServiceBean.getEmail(Mockito.anyString())).thenReturn("johndoe@gmail.com"); String result = systemUnderTest.getId("johndoe"); // 还可以验证jdbcTemplate是否被正确调用 Mockito.verify(jdbcTemplate).queryForObject(Mockito.eq("query here"), Mockito.eq(String.class), Mockito.eq("johndoe@gmail.com")); } }
内容的提问来源于stack exchange,提问作者NightHawk
相关产品推荐
相关产品推荐

