Browse Source
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-32490pull/32648/head
7 changed files with 140 additions and 138 deletions
@ -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