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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:31:55