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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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