|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2024 the original author or authors. |
| 2 | + * Copyright 2002-2025 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
29 | 29 | * ApplicationContexts} for integration tests.
|
30 | 30 | *
|
31 | 31 | * <h3>Examples</h3>
|
| 32 | + * |
32 | 33 | * <p>The following JUnit-based examples demonstrate common configuration
|
33 | 34 | * scenarios for integration tests that require the use of context hierarchies.
|
34 | 35 | *
|
35 | 36 | * <h4>Single Test Class with Context Hierarchy</h4>
|
| 37 | + * |
36 | 38 | * <p>{@code ControllerIntegrationTests} represents a typical integration testing
|
37 | 39 | * scenario for a Spring MVC web application by declaring a context hierarchy
|
38 | 40 | * consisting of two levels, one for the <em>root</em> {@code WebApplicationContext}
|
|
57 | 59 | * }</pre>
|
58 | 60 | *
|
59 | 61 | * <h4>Class Hierarchy with Implicit Parent Context</h4>
|
| 62 | + * |
60 | 63 | * <p>The following test classes define a context hierarchy within a test class
|
61 | 64 | * hierarchy. {@code AbstractWebTests} declares the configuration for a root
|
62 | 65 | * {@code WebApplicationContext} in a Spring-powered web application. Note,
|
|
83 | 86 | * public class RestWebServiceTests extends AbstractWebTests {}</pre>
|
84 | 87 | *
|
85 | 88 | * <h4>Class Hierarchy with Merged Context Hierarchy Configuration</h4>
|
| 89 | + * |
86 | 90 | * <p>The following classes demonstrate the use of <em>named</em> hierarchy levels
|
87 | 91 | * in order to <em>merge</em> the configuration for specific levels in a context
|
88 |
| - * hierarchy. {@code BaseTests} defines two levels in the hierarchy, {@code parent} |
89 |
| - * and {@code child}. {@code ExtendedTests} extends {@code BaseTests} and instructs |
| 92 | + * hierarchy. {@code BaseTests} defines two levels in the hierarchy, {@code "parent"} |
| 93 | + * and {@code "child"}. {@code ExtendedTests} extends {@code BaseTests} and instructs |
90 | 94 | * the Spring TestContext Framework to merge the context configuration for the
|
91 |
| - * {@code child} hierarchy level, simply by ensuring that the names declared via |
| 95 | + * {@code "child"} hierarchy level, simply by ensuring that the names declared via |
92 | 96 | * {@link ContextConfiguration#name} are both {@code "child"}. The result is that
|
93 | 97 | * three application contexts will be loaded: one for {@code "/app-config.xml"},
|
94 | 98 | * one for {@code "/user-config.xml"}, and one for <code>{"/user-config.xml",
|
|
111 | 115 | * public class ExtendedTests extends BaseTests {}</pre>
|
112 | 116 | *
|
113 | 117 | * <h4>Class Hierarchy with Overridden Context Hierarchy Configuration</h4>
|
| 118 | + * |
114 | 119 | * <p>In contrast to the previous example, this example demonstrates how to
|
115 | 120 | * <em>override</em> the configuration for a given named level in a context hierarchy
|
116 | 121 | * by setting the {@link ContextConfiguration#inheritLocations} flag to {@code false}.
|
|
131 | 136 | * )
|
132 | 137 | * public class ExtendedTests extends BaseTests {}</pre>
|
133 | 138 | *
|
| 139 | + * <h4>Context Hierarchies with Bean Overrides</h4> |
| 140 | + * |
| 141 | + * <p>When {@code @ContextHierarchy} is used in conjunction with bean overrides such as |
| 142 | + * {@link org.springframework.test.context.bean.override.convention.TestBean @TestBean}, |
| 143 | + * {@link org.springframework.test.context.bean.override.mockito.MockitoBean @MockitoBean}, or |
| 144 | + * {@link org.springframework.test.context.bean.override.mockito.MockitoSpyBean @MockitoSpyBean}, |
| 145 | + * it may be desirable or necessary to have the override applied to a single level |
| 146 | + * in the context hierarchy. To achieve that, the bean override must specify a |
| 147 | + * context name that matches a name configured via {@link ContextConfiguration#name}. |
| 148 | + * |
| 149 | + * <p>The following test class configures the name of the second hierarchy level to be |
| 150 | + * {@code "user-config"} and simultaneously specifies that the {@code UserService} should |
| 151 | + * be wrapped in a Mockito spy in the context named {@code "user-config"}. Consequently, |
| 152 | + * Spring will only attempt to create the spy in the {@code "user-config"} context and will |
| 153 | + * not attempt to create the spy in the parent context. |
| 154 | + * |
| 155 | + * <pre class="code"> |
| 156 | + * @ExtendWith(SpringExtension.class) |
| 157 | + * @ContextHierarchy({ |
| 158 | + * @ContextConfiguration(classes = AppConfig.class), |
| 159 | + * @ContextConfiguration(classes = UserConfig.class, name = "user-config") |
| 160 | + * }) |
| 161 | + * class IntegrationTests { |
| 162 | + * |
| 163 | + * @MockitoSpyBean(contextName = "user-config") |
| 164 | + * UserService userService; |
| 165 | + * |
| 166 | + * // ... |
| 167 | + * }</pre> |
| 168 | + * |
| 169 | + * <p>When applying bean overrides in different levels of the context hierarchy, you may |
| 170 | + * need to have all of the bean override instances injected into the test class in order |
| 171 | + * to interact with them — for example, to configure stubbing for mocks. However, |
| 172 | + * {@link org.springframework.beans.factory.annotation.Autowired @Autowired} will always |
| 173 | + * inject a matching bean found in the lowest level of the context hierarchy. Thus, to |
| 174 | + * inject bean override instances from specific levels in the context hierarchy, you need |
| 175 | + * to annotate fields with appropriate bean override annotations and configure the name |
| 176 | + * of the context level. |
| 177 | + * |
| 178 | + * <p>The following test class configures the names of the hierarchy levels to be |
| 179 | + * {@code "parent"} and {@code "child"}. It also declares two {@code PropertyService} |
| 180 | + * fields that are configured to create or replace {@code PropertyService} beans with |
| 181 | + * Mockito mocks in the respective contexts, named {@code "parent"} and {@code "child"}. |
| 182 | + * Consequently, the mock from the {@code "parent"} context will be injected into the |
| 183 | + * {@code propertyServiceInParent} field, and the mock from the {@code "child"} context |
| 184 | + * will be injected into the {@code propertyServiceInChild} field. |
| 185 | + * |
| 186 | + * <pre class="code"> |
| 187 | + * @ExtendWith(SpringExtension.class) |
| 188 | + * @ContextHierarchy({ |
| 189 | + * @ContextConfiguration(classes = ParentConfig.class, name = "parent"), |
| 190 | + * @ContextConfiguration(classes = ChildConfig.class, name = "child") |
| 191 | + * }) |
| 192 | + * class IntegrationTests { |
| 193 | + * |
| 194 | + * @MockitoBean(contextName = "parent") |
| 195 | + * PropertyService propertyServiceInParent; |
| 196 | + * |
| 197 | + * @MockitoBean(contextName = "child") |
| 198 | + * PropertyService propertyServiceInChild; |
| 199 | + * |
| 200 | + * // ... |
| 201 | + * }</pre> |
| 202 | + * |
| 203 | + * <h4>Miscellaneous</h4> |
| 204 | + * |
134 | 205 | * <p>This annotation may be used as a <em>meta-annotation</em> to create custom
|
135 | 206 | * <em>composed annotations</em>.
|
136 | 207 | *
|
|
0 commit comments