Skip to content

Commit 02ee5de

Browse files
committed
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
1 parent afbce96 commit 02ee5de

File tree

7 files changed

+140
-138
lines changed

7 files changed

+140
-138
lines changed

framework-docs/modules/ROOT/nav.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
*** xref:testing/testcontext-framework/parallel-test-execution.adoc[]
141141
*** xref:testing/testcontext-framework/support-classes.adoc[]
142142
*** xref:testing/testcontext-framework/aot.adoc[]
143+
*** xref:testing/testcontext-framework/bean-overriding.adoc[]
143144
** xref:testing/webtestclient.adoc[]
144145
** xref:testing/spring-mvc-test-framework.adoc[]
145146
*** xref:testing/spring-mvc-test-framework/server.adoc[]
@@ -183,7 +184,8 @@
183184
***** xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[]
184185
***** xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[]
185186
***** xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[]
186-
***** xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[]
187+
***** xref:testing/annotations/integration-spring/annotation-testbean.adoc[]
188+
***** xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[]
187189
**** xref:testing/annotations/integration-junit4.adoc[]
188190
**** xref:testing/annotations/integration-junit-jupiter.adoc[]
189191
**** xref:testing/annotations/integration-meta.adoc[]

framework-docs/modules/ROOT/pages/core/beans/definition.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ adapt your configuration accordingly. While not recommended, you can silence tho
8989
by setting the `allowBeanDefinitionOverriding` flag to `true`.
9090

9191
NOTE: We acknowledge that overriding beans in a test is convenient, and there is
92-
explicit support for this. For more details please refer to xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[this section].
92+
explicit support for this. For more details please refer to xref:testing/testcontext-framework/bean-overriding.adoc[this section].
9393

9494
[[beans-beanname]]
9595
== Naming Beans

framework-docs/modules/ROOT/pages/testing/annotations/integration-spring.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ Spring's testing annotations include the following:
2828
* xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[`@SqlMergeMode`]
2929
* xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[`@SqlGroup`]
3030
* xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`]
31-
* xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc#spring-testing-annotation-beanoverriding-testbean[`@TestBean`]
32-
* xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc#spring-testing-annotation-beanoverriding-mockitobean[`@MockitoBean` and `@MockitoSpyBean`]
31+
* xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`]
32+
* xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and `@MockitoSpyBean`]
3333

framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-beanoverriding.adoc

Lines changed: 0 additions & 134 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[[spring-testing-annotation-beanoverriding-mockitobean]]
2+
= `@MockitoBean` and `@MockitoSpyBean`
3+
4+
`@MockitoBean` and `@MockitoSpyBean` are used on a test class field to override a bean
5+
with a mocking and spying instance, respectively. In the later case, the original bean
6+
definition is not replaced but instead an early instance is captured and wrapped by the
7+
spy.
8+
9+
By default, the name of the bean to override is derived from the annotated field's name,
10+
but both annotations allows for a specific `name` to be provided. Each annotation also
11+
defines Mockito-specific attributes to fine-tune the mocking details.
12+
13+
The `@MockitoBean` annotation uses the `CREATE_OR_REPLACE_DEFINITION`
14+
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
15+
16+
The `@MockitoSpyBean` annotation uses the `WRAP_EARLY_BEAN`
17+
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy]
18+
and the original instance is wrapped in a Mockito spy.
19+
20+
The following example shows how to configure the bean name for both `@MockitoBean` and
21+
`@MockitoSpyBean` annotations:
22+
23+
[tabs]
24+
======
25+
Java::
26+
+
27+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
28+
----
29+
class OverrideBeanTests {
30+
@MockitoBean(name = "service1") // <1>
31+
private CustomService mockService;
32+
33+
@MockitoSpyBean(name = "service2") // <2>
34+
private CustomService spyService; // <3>
35+
36+
// test case body...
37+
}
38+
----
39+
<1> Mark `mockService` as a Mockito mock override of bean `service1` in this test class
40+
<2> Mark `spyService` as a Mockito spy override of bean `service2` in this test class
41+
<3> Both fields will be injected with the Mockito values (the mock and the spy respectively)
42+
======
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[[spring-testing-annotation-beanoverriding-testbean]]
2+
= `@TestBean`
3+
4+
`@TestBean` is used on a test class field to override a specific bean with an instance
5+
provided by a conventionally named static factory method.
6+
7+
By default, the bean name and the associated factory method name are derived from the
8+
annotated field's name but the annotation allows for specific values to be provided.
9+
10+
The `@TestBean` annotation uses the `REPLACE_DEFINITION`
11+
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
12+
13+
The following example shows how to fully configure the `@TestBean` annotation, with
14+
explicit values equivalent to the default:
15+
16+
[tabs]
17+
======
18+
Java::
19+
+
20+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
21+
----
22+
class OverrideBeanTests {
23+
@TestBean(name = "service", methodName = "serviceTestOverride") // <1>
24+
private CustomService service;
25+
26+
// test case body...
27+
28+
private static CustomService serviceTestOverride() { // <2>
29+
return new MyFakeCustomService();
30+
}
31+
}
32+
----
33+
<1> Mark a field for bean overriding in this test class
34+
<2> The result of this static method will be used as the instance and injected into the field
35+
======
36+
37+
NOTE: The method to invoke is searched in the test class and any enclosing class it might
38+
have, as well as its hierarchy. This typically allows nested test class to rely on the
39+
factory method in the root test class.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
[[spring-testing-beanoverriding]]
2+
= Bean Overriding in Tests
3+
4+
Bean Overriding in Tests refers to the ability to override specific beans in the Context
5+
for a test class, by annotating one or more fields in said test class.
6+
7+
NOTE: This is intended as a less risky alternative to the practice of registering a bean via
8+
`@Bean` with the `DefaultListableBeanFactory` `setAllowBeanDefinitionOverriding` set to
9+
`true`.
10+
11+
The Spring Testing Framework provides two sets of annotations:
12+
xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`],
13+
xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and
14+
`@MockitoSpyBean`]. The former relies purely on Spring, while the later set relies on
15+
the https://site.mockito.org/[Mockito] third party library.
16+
17+
[[spring-testing-beanoverriding-extending]]
18+
== Extending bean override with a custom annotation
19+
20+
The three annotations mentioned above build upon the `@BeanOverride` meta-annotation
21+
and associated infrastructure, which allows to define custom bean overriding variants.
22+
23+
To create an extension, the following is needed:
24+
25+
- An annotation meta-annotated with `@BeanOverride` that defines the
26+
`BeanOverrideProcessor` to use.
27+
- The `BeanOverrideProcessor` implementation itself.
28+
- One or more concrete `OverrideMetadata` implementations provided by the processor.
29+
30+
The Spring TestContext Framework includes infrastructure classes that support bean
31+
overriding: a `BeanFactoryPostProcessor`, a `TestExecutionListener` and a
32+
`ContextCustomizerFactory`.
33+
The later two are automatically registered via the Spring TestContext Framework
34+
`spring.factories` file, and are responsible for setting up the rest of the infrastructure.
35+
36+
The test classes are parsed looking for any field meta-annotated with `@BeanOverride`,
37+
instantiating the relevant `BeanOverrideProcessor` in order to register an
38+
`OverrideMetadata`.
39+
40+
Then the `BeanOverrideBeanFactoryPostProcessor` will use that information to alter the
41+
context, registering and replacing bean definitions as defined by each metadata
42+
`BeanOverrideStrategy`:
43+
44+
- `REPLACE_DEFINITION`: replaces the bean definition. If it is not present in the
45+
context, an exception is thrown.
46+
- `CREATE_OR_REPLACE_DEFINITION`: replaces the bean definition if the bean definition
47+
does not exist, or create one if it is not.
48+
- `WRAP_BEAN`: get the original instance early so that it can be wrapped.
49+
50+
NOTE: The Bean Overriding infrastructure does not include any bean resolution step,
51+
unlike an `@Autowired`-annotated field for instance. As such, the name of the bean to
52+
override must be somehow provided to or computed by the `BeanOverrideProcessor`.
53+
Typically, the user provides the name one way or the other.

0 commit comments

Comments
 (0)