Bean Overriding in Tests

Bean overriding in tests refers to the ability to override specific beans in the ApplicationContext for a test class, by annotating one or more fields in the test class.spring-doc.cn

This feature is intended as a less risky alternative to the practice of registering a bean via @Bean with the DefaultListableBeanFactory setAllowBeanDefinitionOverriding flag set to true.

The Spring TestContext framework provides two sets of annotations for bean overriding.spring-doc.cn

The former relies purely on Spring, while the latter set relies on the Mockito third-party library.spring-doc.cn

Custom Bean Override Support

The three annotations mentioned above build upon the @BeanOverride meta-annotation and associated infrastructure, which allows one to define custom bean overriding variants.spring-doc.cn

To implement custom bean override support, the following is needed:spring-doc.cn

  • An annotation meta-annotated with @BeanOverride that defines the BeanOverrideProcessor to usespring-doc.cn

  • A custom BeanOverrideProcessor implementationspring-doc.cn

  • One or more concrete BeanOverrideHandler implementations created by the processorspring-doc.cn

The Spring TestContext framework includes implementations of the following APIs that support bean overriding and are responsible for setting up the rest of the infrastructure.spring-doc.cn

The spring-test module registers implementations of the latter two (BeanOverrideContextCustomizerFactory and BeanOverrideTestExecutionListener) in its META-INF/spring.factories properties file.spring-doc.cn

The bean overriding infrastructure searches in test classes for any field meta-annotated with @BeanOverride and instantiates the corresponding BeanOverrideProcessor which is responsible for creating an appropriate BeanOverrideHandler.spring-doc.cn

The internal BeanOverrideBeanFactoryPostProcessor then uses bean override handlers to alter the test’s ApplicationContext by creating, replacing, or wrapping beans as defined by the corresponding BeanOverrideStrategy:spring-doc.cn

REPLACE

Replaces the bean. Throws an exception if a corresponding bean does not exist.spring-doc.cn

REPLACE_OR_CREATE

Replaces the bean if it exists. Creates a new bean if a corresponding bean does not exist.spring-doc.cn

WRAP

Retrieves the original bean and wraps it.spring-doc.cn

Only singleton beans can be overridden. Any attempt to override a non-singleton bean will result in an exception.spring-doc.cn

When replacing a bean created by a FactoryBean, the FactoryBean itself will be replaced with a singleton bean corresponding to bean override instance created by the applicable BeanOverrideHandler.spring-doc.cn

When wrapping a bean created by a FactoryBean, the object created by the FactoryBean will be wrapped, not the FactoryBean itself.spring-doc.cn

In contrast to Spring’s autowiring mechanism (for example, resolution of an @Autowired field), the bean overriding infrastructure in the TestContext framework has limited heuristics it can perform to locate a bean. Either the BeanOverrideProcessor can compute the name of the bean to override, or it can be unambiguously selected given the type of the annotated field and its qualifying annotations.spring-doc.cn

Typically, the bean is selected "by type" by the BeanOverrideFactoryPostProcessor. Alternatively, the user can directly provide the bean name in the custom annotation.spring-doc.cn

BeanOverrideProcessor implementations may also internally compute a bean name based on a convention or some other method.spring-doc.cn