Document bean override in TestContext framework section of the manual
This change splits the documentation in the reference manual: the `@TestBean`, `@MockitoBean` and `@MockitoSpyBean` annotations are kept in the appendix and the general documentation about the feature is moved into a dedicated sub-section of the TCF section. Close gh-32490
This commit is contained in:
parent
afbce96fb7
commit
02ee5de470
|
@ -140,6 +140,7 @@
|
|||
*** xref:testing/testcontext-framework/parallel-test-execution.adoc[]
|
||||
*** xref:testing/testcontext-framework/support-classes.adoc[]
|
||||
*** xref:testing/testcontext-framework/aot.adoc[]
|
||||
*** xref:testing/testcontext-framework/bean-overriding.adoc[]
|
||||
** xref:testing/webtestclient.adoc[]
|
||||
** xref:testing/spring-mvc-test-framework.adoc[]
|
||||
*** xref:testing/spring-mvc-test-framework/server.adoc[]
|
||||
|
@ -183,7 +184,8 @@
|
|||
***** xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-testbean.adoc[]
|
||||
***** xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[]
|
||||
**** xref:testing/annotations/integration-junit4.adoc[]
|
||||
**** xref:testing/annotations/integration-junit-jupiter.adoc[]
|
||||
**** xref:testing/annotations/integration-meta.adoc[]
|
||||
|
|
|
@ -89,7 +89,7 @@ adapt your configuration accordingly. While not recommended, you can silence tho
|
|||
by setting the `allowBeanDefinitionOverriding` flag to `true`.
|
||||
|
||||
NOTE: We acknowledge that overriding beans in a test is convenient, and there is
|
||||
explicit support for this. For more details please refer to xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[this section].
|
||||
explicit support for this. For more details please refer to xref:testing/testcontext-framework/bean-overriding.adoc[this section].
|
||||
|
||||
[[beans-beanname]]
|
||||
== Naming Beans
|
||||
|
|
|
@ -28,6 +28,6 @@ Spring's testing annotations include the following:
|
|||
* xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[`@SqlMergeMode`]
|
||||
* xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[`@SqlGroup`]
|
||||
* xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`]
|
||||
* xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc#spring-testing-annotation-beanoverriding-testbean[`@TestBean`]
|
||||
* xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc#spring-testing-annotation-beanoverriding-mockitobean[`@MockitoBean` and `@MockitoSpyBean`]
|
||||
* xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`]
|
||||
* xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and `@MockitoSpyBean`]
|
||||
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
[[spring-testing-annotation-beanoverriding]]
|
||||
= Bean Overriding in Tests
|
||||
|
||||
Bean Overriding in Tests refers to the ability to override specific beans in the Context
|
||||
for a test class, by annotating one or more fields in said test class.
|
||||
|
||||
NOTE: This is intended as a less risky alternative to the practice of registering a bean via
|
||||
`@Bean` with the `DefaultListableBeanFactory` `setAllowBeanDefinitionOverriding` set to
|
||||
`true`.
|
||||
|
||||
The Spring Testing Framework provides two sets of annotations presented below. One relies
|
||||
purely on Spring, while the second set relies on the Mockito third party library.
|
||||
|
||||
[[spring-testing-annotation-beanoverriding-testbean]]
|
||||
== `@TestBean`
|
||||
|
||||
`@TestBean` is used on a test class field to override a specific bean with an instance
|
||||
provided by a conventionally named static method.
|
||||
|
||||
By default, the bean name and the associated static method name are derived from the
|
||||
annotated field's name, but the annotation allows for specific values to be provided.
|
||||
|
||||
The `@TestBean` annotation uses the `REPLACE_DEFINITION`
|
||||
xref:#spring-testing-annotation-beanoverriding-extending[strategy for test bean overriding].
|
||||
|
||||
The following example shows how to fully configure the `@TestBean` annotation, with
|
||||
explicit values equivalent to the default:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@TestBean(name = "service", methodName = "serviceTestOverride") // <1>
|
||||
private CustomService service;
|
||||
|
||||
// test case body...
|
||||
|
||||
private static CustomService serviceTestOverride() { // <2>
|
||||
return new MyFakeCustomService();
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Mark a field for bean overriding in this test class
|
||||
<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 rely on the
|
||||
method to use in the root test class.
|
||||
|
||||
[[spring-testing-annotation-beanoverriding-mockitobean]]
|
||||
== `@MockitoBean` and `@MockitoSpyBean`
|
||||
|
||||
`@MockitoBean` and `@MockitoSpyBean` are used on a test class field to override a bean
|
||||
with a mocking and spying instance, respectively. In the later case, the original bean
|
||||
definition is not replaced but instead an early instance is captured and wrapped by the
|
||||
spy.
|
||||
|
||||
By default, the name of the bean to override is derived from the annotated field's name,
|
||||
but both annotations allows for a specific `name` to be provided. Each annotation also
|
||||
defines Mockito-specific attributes to fine-tune the mocking details.
|
||||
|
||||
The `@MockitoBean` annotation uses the `CREATE_OR_REPLACE_DEFINITION`
|
||||
xref:#spring-testing-annotation-beanoverriding-extending[strategy for test bean overriding].
|
||||
|
||||
The `@MockitoSpyBean` annotation uses the `WRAP_EARLY_BEAN`
|
||||
xref:#spring-testing-annotation-beanoverriding-extending[strategy] and the original instance
|
||||
is wrapped in a Mockito spy.
|
||||
|
||||
The following example shows how to configure the bean name for both `@MockitoBean` and
|
||||
`@MockitoSpyBean` annotations:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@MockitoBean(name = "service1") // <1>
|
||||
private CustomService mockService;
|
||||
|
||||
@MockitoSpyBean(name = "service2") // <2>
|
||||
private CustomService spyService; // <3>
|
||||
|
||||
// test case body...
|
||||
}
|
||||
----
|
||||
<1> Mark `mockService` as a Mockito mock override of bean `service1` in this test class
|
||||
<2> Mark `spyService` as a Mockito spy override of bean `service2` in this test class
|
||||
<3> Both fields will be injected with the Mockito values (the mock and the spy respectively)
|
||||
======
|
||||
|
||||
|
||||
[[spring-testing-annotation-beanoverriding-extending]]
|
||||
== Extending bean override with a custom annotation
|
||||
|
||||
The three annotations introduced above build upon the `@BeanOverride` meta-annotation
|
||||
and associated infrastructure, which allows to define custom bean overriding variants.
|
||||
|
||||
To create an extension, the following is needed:
|
||||
|
||||
- An annotation meta-annotated with `@BeanOverride` that defines the
|
||||
`BeanOverrideProcessor` to use.
|
||||
- The `BeanOverrideProcessor` implementation itself.
|
||||
- One or more concrete `OverrideMetadata` implementations provided by the processor.
|
||||
|
||||
The Spring TestContext Framework includes infrastructure classes that support bean
|
||||
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 `BeanOverrideBeanFactoryPostProcessor` will use that information to alter the
|
||||
context, registering and replacing bean definitions as defined by each metadata
|
||||
`BeanOverrideStrategy`:
|
||||
|
||||
- `REPLACE_DEFINITION`: replaces the bean definition. If it is not present in the
|
||||
context, an exception is thrown.
|
||||
- `CREATE_OR_REPLACE_DEFINITION`: replaces the bean definition if the bean definition
|
||||
does not exist, or create one if it is not.
|
||||
- `WRAP_BEAN`: get the original instance early so that it can be wrapped.
|
||||
|
||||
NOTE: The Bean Overriding infrastructure does not include any bean resolution step,
|
||||
unlike an `@Autowired`-annotated field for instance. As such, the name of the bean to
|
||||
override must be somehow provided to or computed by the `BeanOverrideProcessor`.
|
||||
Typically, the user provides the name one way or the other.
|
|
@ -0,0 +1,42 @@
|
|||
[[spring-testing-annotation-beanoverriding-mockitobean]]
|
||||
= `@MockitoBean` and `@MockitoSpyBean`
|
||||
|
||||
`@MockitoBean` and `@MockitoSpyBean` are used on a test class field to override a bean
|
||||
with a mocking and spying instance, respectively. In the later case, the original bean
|
||||
definition is not replaced but instead an early instance is captured and wrapped by the
|
||||
spy.
|
||||
|
||||
By default, the name of the bean to override is derived from the annotated field's name,
|
||||
but both annotations allows for a specific `name` to be provided. Each annotation also
|
||||
defines Mockito-specific attributes to fine-tune the mocking details.
|
||||
|
||||
The `@MockitoBean` annotation uses the `CREATE_OR_REPLACE_DEFINITION`
|
||||
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
|
||||
|
||||
The `@MockitoSpyBean` annotation uses the `WRAP_EARLY_BEAN`
|
||||
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy]
|
||||
and the original instance is wrapped in a Mockito spy.
|
||||
|
||||
The following example shows how to configure the bean name for both `@MockitoBean` and
|
||||
`@MockitoSpyBean` annotations:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@MockitoBean(name = "service1") // <1>
|
||||
private CustomService mockService;
|
||||
|
||||
@MockitoSpyBean(name = "service2") // <2>
|
||||
private CustomService spyService; // <3>
|
||||
|
||||
// test case body...
|
||||
}
|
||||
----
|
||||
<1> Mark `mockService` as a Mockito mock override of bean `service1` in this test class
|
||||
<2> Mark `spyService` as a Mockito spy override of bean `service2` in this test class
|
||||
<3> Both fields will be injected with the Mockito values (the mock and the spy respectively)
|
||||
======
|
|
@ -0,0 +1,39 @@
|
|||
[[spring-testing-annotation-beanoverriding-testbean]]
|
||||
= `@TestBean`
|
||||
|
||||
`@TestBean` is used on a test class field to override a specific bean with an instance
|
||||
provided by a conventionally named static factory method.
|
||||
|
||||
By default, the bean name and the associated factory method name are derived from the
|
||||
annotated field's name but the annotation allows for specific values to be provided.
|
||||
|
||||
The `@TestBean` annotation uses the `REPLACE_DEFINITION`
|
||||
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
|
||||
|
||||
The following example shows how to fully configure the `@TestBean` annotation, with
|
||||
explicit values equivalent to the default:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
class OverrideBeanTests {
|
||||
@TestBean(name = "service", methodName = "serviceTestOverride") // <1>
|
||||
private CustomService service;
|
||||
|
||||
// test case body...
|
||||
|
||||
private static CustomService serviceTestOverride() { // <2>
|
||||
return new MyFakeCustomService();
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Mark a field for bean overriding in this test class
|
||||
<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 rely on the
|
||||
factory method in the root test class.
|
|
@ -0,0 +1,53 @@
|
|||
[[spring-testing-beanoverriding]]
|
||||
= Bean Overriding in Tests
|
||||
|
||||
Bean Overriding in Tests refers to the ability to override specific beans in the Context
|
||||
for a test class, by annotating one or more fields in said test class.
|
||||
|
||||
NOTE: This is intended as a less risky alternative to the practice of registering a bean via
|
||||
`@Bean` with the `DefaultListableBeanFactory` `setAllowBeanDefinitionOverriding` set to
|
||||
`true`.
|
||||
|
||||
The Spring Testing Framework provides two sets of annotations:
|
||||
xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`],
|
||||
xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and
|
||||
`@MockitoSpyBean`]. The former relies purely on Spring, while the later set relies on
|
||||
the https://site.mockito.org/[Mockito] third party library.
|
||||
|
||||
[[spring-testing-beanoverriding-extending]]
|
||||
== Extending bean override with a custom annotation
|
||||
|
||||
The three annotations mentioned above build upon the `@BeanOverride` meta-annotation
|
||||
and associated infrastructure, which allows to define custom bean overriding variants.
|
||||
|
||||
To create an extension, the following is needed:
|
||||
|
||||
- An annotation meta-annotated with `@BeanOverride` that defines the
|
||||
`BeanOverrideProcessor` to use.
|
||||
- The `BeanOverrideProcessor` implementation itself.
|
||||
- One or more concrete `OverrideMetadata` implementations provided by the processor.
|
||||
|
||||
The Spring TestContext Framework includes infrastructure classes that support bean
|
||||
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 `BeanOverrideBeanFactoryPostProcessor` will use that information to alter the
|
||||
context, registering and replacing bean definitions as defined by each metadata
|
||||
`BeanOverrideStrategy`:
|
||||
|
||||
- `REPLACE_DEFINITION`: replaces the bean definition. If it is not present in the
|
||||
context, an exception is thrown.
|
||||
- `CREATE_OR_REPLACE_DEFINITION`: replaces the bean definition if the bean definition
|
||||
does not exist, or create one if it is not.
|
||||
- `WRAP_BEAN`: get the original instance early so that it can be wrapped.
|
||||
|
||||
NOTE: The Bean Overriding infrastructure does not include any bean resolution step,
|
||||
unlike an `@Autowired`-annotated field for instance. As such, the name of the bean to
|
||||
override must be somehow provided to or computed by the `BeanOverrideProcessor`.
|
||||
Typically, the user provides the name one way or the other.
|
Loading…
Reference in New Issue