Improve Bean Overriding support, testing and documentation
This commit improves on the bean overriding feature in several ways: the API is simplified and polished (metadata and processor contracts, etc...). The commit also reworks infrastructure classes (context customizer, test execution listener, BeanOverrideBeanFactoryPostProcessor, etc...). Parsing of annotations is now fully stateless. In order to avoid OverrideMetadata in bean definition and to make a first step towards AOT support, the BeanOverrideBeanFactoryPostProcessor now delegates to a BeanOverrideRegistrar to track classes to parse, the metadata-related state as well as for the field injection methods for tests. Lastly, this commit increases the test coverage for the provided annotations and adds integration tests and fixes a few `@TestBean` issues.
This commit is contained in:
@@ -47,6 +47,9 @@ Java::
|
||||
<2> The result of this static method will be used as the instance and injected into the field
|
||||
======
|
||||
|
||||
NOTE: The method to invoke is searched in the test class and any enclosing class it might
|
||||
have, as well as its hierarchy. This typically allows nested test class to provide the
|
||||
method to use in the root test class.
|
||||
|
||||
[[spring-testing-annotation-beanoverriding-mockitobean]]
|
||||
== `@MockitoBean` and `@MockitoSpyBean`
|
||||
@@ -100,32 +103,31 @@ and associated infrastructure, which allows to define custom bean overriding var
|
||||
|
||||
In order to provide an extension, three classes are needed:
|
||||
|
||||
- A concrete `BeanOverrideProcessor<P>`.
|
||||
- A concrete `OverrideMetadata` created by said processor.
|
||||
- A concrete `BeanOverrideProcessor` implementation, `P`.
|
||||
- One or more concrete `OverrideMetadata` implementations created by said processor.
|
||||
- An annotation meta-annotated with `@BeanOverride(P.class)`.
|
||||
|
||||
The Spring TestContext Framework includes infrastructure classes that support bean
|
||||
overriding: a `BeanPostProcessor`, a `TestExecutionListener` and a `ContextCustomizerFactory`.
|
||||
These are automatically registered via the Spring TestContext Framework `spring.factories`
|
||||
file.
|
||||
overriding: a `BeanFactoryPostProcessor`, a `TestExecutionListener` and a `ContextCustomizerFactory`.
|
||||
The later two are automatically registered via the Spring TestContext Framework
|
||||
`spring.factories` file, and are responsible for setting up the rest of the infrastructure.
|
||||
|
||||
The test classes are parsed looking for any field meta-annotated with `@BeanOverride`,
|
||||
instantiating the relevant `BeanOverrideProcessor` in order to register an `OverrideMetadata`.
|
||||
|
||||
Then the `BeanOverrideBeanPostProcessor` will use that information to alter the Context,
|
||||
registering and replacing bean definitions as influenced by each metadata
|
||||
Then the `BeanOverrideBeanFactoryPostProcessor` will use that information to alter the
|
||||
Context, registering and replacing bean definitions as influenced by each metadata
|
||||
`BeanOverrideStrategy`:
|
||||
|
||||
- `REPLACE_DEFINITION`: the bean post-processor replaces the bean definition.
|
||||
If it is not present in the context, an exception is thrown.
|
||||
- `CREATE_OR_REPLACE_DEFINITION`: same as above but if the bean definition is not present
|
||||
in the context, one is created
|
||||
- `WRAP_EARLY_BEAN`: an original instance is obtained via
|
||||
`SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(Object, String)` and
|
||||
provided to the processor during `OverrideMetadata` creation.
|
||||
- `WRAP_EARLY_BEAN`: an original instance is obtained and passed to the `OverrideMetadata`
|
||||
when the override instance is created.
|
||||
|
||||
NOTE: The Bean Overriding infrastructure works best with singleton beans. It also doesn't
|
||||
include any bean resolution (unlike e.g. an `@Autowired`-annotated field). As such, the
|
||||
name of the bean to override MUST be somehow provided to or computed by the
|
||||
`BeanOverrideProcessor`. Typically, the end user provides the name as part of the custom
|
||||
annotation's attributes, or the annotated field's name.
|
||||
NOTE: The Bean Overriding infrastructure doesn't include any bean resolution step
|
||||
(unlike e.g. an `@Autowired`-annotated field). As such, the name of the bean to override
|
||||
MUST be somehow provided to or computed by the `BeanOverrideProcessor`. Typically, the end
|
||||
user provides the name as part of the custom annotation's attributes, or the annotated
|
||||
field's name.
|
||||
Reference in New Issue
Block a user