Bean Overriding in Tests

测试中的 bean 重写是指覆盖测试类中 ApplicationContext 的特定 bean 的能力,做法是为测试类中的一个或多个字段添加注解。

此功能旨在提供一种降低风险的替代方案,用于通过 @Bean 注册 bean,并将 DefaultListableBeanFactory``setAllowBeanDefinitionOverriding 标志设为 true 的做法。

Spring 测试上下文框架提供了两组 bean 重写注解。

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

Custom Bean Override Support

上面提到的三个注解以 @BeanOverride 元注解和关联的基础设施为基础,它允许人们定义自定义 bean 重写变体。

若要创建自定义 bean 重写支持,需要以下内容:

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

  • A custom BeanOverrideProcessor implementation

  • 处理器提供的具体 OverrideMetadata 实现

Spring 测试上下文框架包括支持 bean 重写的以下 API 实现,并负责设置其余的基础设施。

  • a BeanFactoryPostProcessor

  • a ContextCustomizerFactory

  • a TestExecutionListener

spring-test 模块在其 https://github.com/spring-projects/spring-framework/tree/main/spring-test/src/main/resources/META-INF/spring.factories[META-INF/spring.factories`properties 文件中注册了后两个实现(`BeanOverrideContextCustomizerFactoryBeanOverrideTestExecutionListener)。

bean 重写基础设施在测试类中搜索任何使用 @BeanOverride 进行元注解的字段,并实例化负责注册适当 OverrideMetadata 的相应 BeanOverrideProcessor

然后,内部 BeanOverrideBeanFactoryPostProcessor 使用该信息,通过注册和替换由相应 BeanOverrideStrategy 定义的 bean 定义,来更改测试的 ApplicationContext

  • REPLACE_DEFINITION:替换 Bean 定义。如果相应的 Bean 定义不存在,则会抛出异常。

  • REPLACE_OR_CREATE_DEFINITION:如果 Bean 定义存在,则替换该定义。如果相应的 Bean 定义不存在,则创建新的 Bean 定义。

  • WRAP_BEAN:检索原始 Bean 实例并对其进行封装。

然而,与 Spring 的自动装配机制(例如,解析 @Autowired 字段)相反,测试上下文框架中的 bean 重写基础设施在定位 bean 时执行的启发式方法有限。BeanOverrideProcessor 可以计算要重写的 bean 的名称,或者根据带有注解的字段的类型以及它的限定注解明确挑选。 通常,BeanOverrideFactoryPostProcessor 根据类型选择 bean。此外,用户可以直接在自定义注解中提供 bean 名称。 某些 BeanOverrideProcessor 实现还可以基于约定或其他高级方法在内部计算 bean 名称。