测试中的 Bean 覆盖

测试中的 Bean 覆盖是指通过为测试类中的一个或多个字段添加注解,覆盖ApplicationContext 中特定 Bean 的能力。

此功能旨在作为一种风险较低的替代方案,替代通过@BeanDefaultListableBeanFactorysetAllowBeanDefinitionOverriding 标志设置为true 来注册 Bean 的做法。

Spring TestContext 框架提供两组用于 Bean 覆盖的注解。

前者完全依赖于 Spring,而后者则依赖于Mockito 第三方库。

自定义 Bean 覆盖支持

上面提到的三个注解建立在@BeanOverride 元注解和相关基础设施之上,这允许定义自定义 Bean 覆盖变体。

要实现自定义 Bean 覆盖支持,需要以下内容

  • @BeanOverride 元注解的注解,定义要使用的BeanOverrideProcessor

  • 自定义BeanOverrideProcessor 实现

  • 由处理器创建的一个或多个具体的BeanOverrideHandler 实现

Spring TestContext 框架包含以下 API 的实现,这些 API 支持 Bean 覆盖,并负责设置其余基础设施。

  • 一个BeanFactoryPostProcessor

  • 一个ContextCustomizerFactory

  • 一个TestExecutionListener

spring-test 模块在其META-INF/spring.factories 属性文件 中注册后两个(BeanOverrideContextCustomizerFactoryBeanOverrideTestExecutionListener)的实现。

Bean 覆盖基础设施在测试类中搜索任何用@BeanOverride 元注解的字段,并实例化相应的BeanOverrideProcessor,该处理器负责创建适当的BeanOverrideHandler

内部的BeanOverrideBeanFactoryPostProcessor 然后使用 Bean 覆盖处理器通过创建、替换或包装由相应的BeanOverrideStrategy 定义的 Bean 来更改测试的ApplicationContext

REPLACE

替换 Bean。如果相应的 Bean 不存在,则抛出异常。

REPLACE_OR_CREATE

如果 Bean 存在则替换它。如果相应的 Bean 不存在,则创建一个新的 Bean。

WRAP

检索原始 Bean 并包装它。

只能覆盖单例 Bean。任何尝试覆盖非单例 Bean 的操作都将导致异常。

当替换由FactoryBean 创建的 Bean 时,FactoryBean 本身将被替换为与由适用BeanOverrideHandler 创建的 Bean 覆盖实例相对应的单例 Bean。

当包装由FactoryBean 创建的 Bean 时,将包装由FactoryBean 创建的对象,而不是FactoryBean 本身。

与 Spring 的自动装配机制(例如,@Autowired 字段的解析)相比,TestContext 框架中的 Bean 覆盖基础设施可以执行的启发式方法有限。BeanOverrideProcessor 可以计算要覆盖的 Bean 的名称,或者可以在给定带注释的字段的类型及其限定注解的情况下明确选择它。

通常,Bean 由BeanOverrideFactoryPostProcessor“按类型”选择。或者,用户可以在自定义注解中直接提供 Bean 名称。

BeanOverrideProcessor 实现也可以基于约定或其他方法在内部计算 Bean 名称。