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

Spring单元测试Mockito Mock @Autowired字段返回null问题

Spring Boot单元测试Mock注入失效、Stub返回null修复方案

直接导致问题的根因

  • 测试类注解冲突:@RunWith(SpringRunner.class)是JUnit4专属的Spring测试运行器,@ExtendWith(MockitoExtension.class)是JUnit5专属的Mockito扩展,二者同时声明会导致测试上下文初始化冲突,Mock的Stub逻辑被上下文覆盖失效
  • 参数匹配逻辑错误:初始化方法中新建的InputObj实例是测试侧的独立对象,业务逻辑执行时内部生成的InputObj实例和该实例不是同一个引用,Mockito默认按对象equals做严格参数匹配,匹配失败时Mock方法默认返回null
  • 注解选型错误:Spring上下文托管的Bean做Mock替换时,用@Mock+@InjectMocks、手动Mockito.mock()生成的Mock对象不会注册到Spring容器,业务类注入的还是容器中真实的Comm实例,会直接执行真实方法逻辑
  • @AsyncAOP代理干扰:标注@Async的类会被Spring生成代理子类,代理对象可能绕过注入的Mock引用,调用真实Bean的方法
  • 代码语法问题:原测试类声明public class testProcessorClass()带多余括号,不符合Java语法,类名也不符合大驼峰规范,会直接导致编译/运行异常

可直接落地的修复步骤(无需修改业务类构造函数)

1. 清理冲突的测试类注解

保留和JUnit4匹配的Spring测试注解,删除不兼容的JUnit5扩展,同时禁用测试环境的异步自动配置,避免AOP代理干扰:

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.task.execution.async.enabled=false")
@ContextConfiguration(classes = {...}) // 原有配置类保留
public class TestProcessorClass {

2. 修正Mock注入与Stub逻辑

使用@MockBean将Comm的Mock对象注册到Spring容器,替换原有真实Bean;Stub时使用宽松参数匹配器,避免对象引用不一致导致的匹配失败:

@Autowired 
Cache cache;

@MockBean 
Comm comm; 

@Autowired 
Processor processor; 

@Before
public void init() {
    ReturnData presetReturn = new ReturnData();
    // 任意InputObj实例都匹配,第二个参数精确匹配硬编码的"id"
    Mockito.doReturn(presetReturn)
           .when(comm)
           .checkOut(Mockito.any(InputObj.class), Mockito.eq("id"));
}

@Test
public void testProcessorMethod() {
    // 注意核对方法名:原Processor类贴出的方法名是processResponse,不要写错成processRequest
    Request reqData = new Request(versionId, dataString);
    Response response = processor.processResponse(reqData);
    // 后续断言逻辑
}

如果需要严格校验入参,不要用any(InputObj.class),可以改用Mockito.argThat()自定义匹配规则,校验InputObj的字段值符合预期即可,不需要对象引用完全相等。


额外注意事项

注意:@MockBean是Spring Boot Test提供的专属注解,作用是将生成的Mock对象注册到Spring应用上下文,自动替换容器中同类型的真实Bean,是启动Spring上下文的集成测试场景下替换依赖的正确方式,不要和纯Mockito场景的@Mock注解混用。

  • 不要在Spring集成测试场景下混用@InjectMocks:该注解是Mockito独立依赖注入的标记,不会将Mock注入到Spring容器托管的Bean中,仅适用于不启动Spring上下文的纯单元测试
  • 不要手动调用Mockito.mock()生成Spring依赖的Mock:手动生成的对象不在Spring容器中,无法替换业务类自动注入的真实实例
  • 如果需要保留@Async的异步执行逻辑,不要禁用异步配置,改为注入AsyncTaskExecutor手动等待异步任务执行完成后再做断言即可,Stub逻辑写法保持不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:48:18