@MockBean注入构造方法自动装配组件:测试类为何能正常运行?
关于@MockkBean构造方法注入的运行疑问
根据Spring Boot官方文档说明:
按类型注册时,上下文内任何匹配类型(包括子类)的现有单一Bean都会被Mock替换
但如果被测类通过构造方法自动装配依赖,比如下面这段Kotlin代码(推测@MockkBean和@MockBean在依赖注入表现上一致):
@RunWith(SpringRunner.class) class ExampleTests @Autowired constructor(val userOfService: UserOfService) { @MockkBean private lateinit var service: ExampleService // 测试逻辑... }
我原本以为这段代码会执行失败——因为Spring要实例化ExampleTests,必须先拿到UserOfService的有效实例,但此时上下文里还没有ExampleService类型的Bean。可实际这段代码能正常运行,这是为什么?
原因解析
这是因为Spring Boot测试框架处理@MockBean(包括@MockkBean这类第三方扩展注解)时,会把Mock Bean的创建和注册步骤提前到上下文初始化的最早期,优先级远高于测试类的实例化流程。
具体执行顺序是:
- 第一步:Spring Runner启动后,先扫描测试类的所有注解,发现
@MockkBean声明后,立刻为ExampleService创建Mock实例,并将其注册到应用上下文。 - 第二步:初始化上下文里的其他Bean(比如
UserOfService),此时ExampleService的Mock已经存在,UserOfService的构造方法可以正常注入依赖,顺利完成实例化。 - 第三步:最后才会实例化测试类
ExampleTests,同时完成userOfService的自动注入,以及service字段的Mock实例赋值。
简单来说,Mock Bean的创建时机比你预想的早得多,在UserOfService和测试类实例化之前就已经准备好,自然不会出现依赖缺失的问题。
另外补充:如果UserOfService是通过组件扫描注册的Spring Bean,Spring测试框架会严格保证Bean的依赖注入顺序,Mock Bean会提前就位来满足它的依赖需求。
内容的提问来源于stack exchange,提问作者David Kubecka
相关产品推荐
相关产品推荐

