1818
1919import java .lang .reflect .Field ;
2020import java .util .List ;
21- import java .util .function .BiConsumer ;
2221
2322import org .springframework .test .context .TestContext ;
2423import org .springframework .test .context .support .AbstractTestExecutionListener ;
2524import org .springframework .test .context .support .DependencyInjectionTestExecutionListener ;
2625import org .springframework .util .ReflectionUtils ;
2726
2827/**
29- * {@code TestExecutionListener} that enables Bean Override support in tests,
30- * injecting overridden beans in appropriate fields of the test instance.
28+ * {@code TestExecutionListener} that enables {@link BeanOverride @BeanOverride}
29+ * support in tests, by injecting overridden beans in appropriate fields of the
30+ * test instance.
3131 *
3232 * @author Simon Baslé
33+ * @author Sam Brannen
3334 * @since 6.2
3435 */
3536public class BeanOverrideTestExecutionListener extends AbstractTestExecutionListener {
@@ -42,64 +43,57 @@ public int getOrder() {
4243 return LOWEST_PRECEDENCE - 50 ;
4344 }
4445
45- @ Override
46- public void prepareTestInstance (TestContext testContext ) throws Exception {
47- injectFields (testContext );
48- }
49-
50- @ Override
51- public void beforeTestMethod (TestContext testContext ) throws Exception {
52- reinjectFieldsIfNecessary (testContext );
53- }
54-
5546 /**
56- * Process the test instance and make sure that fields flagged for bean
57- * overriding are injected with the overridden bean instance.
47+ * Inject each {@link BeanOverride @BeanOverride} field in the
48+ * {@linkplain Object test instance} of the supplied {@linkplain TestContext
49+ * test context} with a corresponding bean override instance.
5850 */
59- protected void injectFields ( TestContext testContext ) {
60- postProcessFields ( testContext , ( testMetadata , registrar ) ->
61- registrar . inject ( testMetadata . testInstance , testMetadata . overrideMetadata ) );
51+ @ Override
52+ public void prepareTestInstance ( TestContext testContext ) throws Exception {
53+ injectFields ( testContext , false );
6254 }
6355
6456 /**
65- * Process the test instance and make sure that fields flagged for bean
66- * overriding are injected with the overridden bean instance, if necessary.
67- * <p>If a fresh instance is required, the field is nulled out and then
68- * re-injected with the overridden bean instance.
57+ * Re-inject each {@link BeanOverride @BeanOverride} field in the
58+ * {@linkplain Object test instance} of the supplied {@linkplain TestContext
59+ * test context} with a corresponding bean override instance.
6960 * <p>This method does nothing if the
70- * {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
71- * attribute is not present in the {@code TestContext} with a value of {@link Boolean#TRUE}.
61+ * {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
62+ * REINJECT_DEPENDENCIES_ATTRIBUTE} attribute is not present in the
63+ * {@code TestContext} with a value of {@link Boolean#TRUE}.
7264 */
73- protected void reinjectFieldsIfNecessary (TestContext testContext ) throws Exception {
74- if (Boolean .TRUE .equals (
75- testContext .getAttribute (DependencyInjectionTestExecutionListener .REINJECT_DEPENDENCIES_ATTRIBUTE ))) {
76-
77- postProcessFields (testContext , (testMetadata , registrar ) -> {
78- Object testInstance = testMetadata .testInstance ;
79- Field field = testMetadata .overrideMetadata .getField ();
80- ReflectionUtils .makeAccessible (field );
81- ReflectionUtils .setField (field , testInstance , null );
82- registrar .inject (testInstance , testMetadata .overrideMetadata );
83- });
65+ @ Override
66+ public void beforeTestMethod (TestContext testContext ) throws Exception {
67+ Object reinjectDependenciesAttribute = testContext .getAttribute (
68+ DependencyInjectionTestExecutionListener .REINJECT_DEPENDENCIES_ATTRIBUTE );
69+ if (Boolean .TRUE .equals (reinjectDependenciesAttribute )) {
70+ injectFields (testContext , true );
8471 }
8572 }
8673
87- private void postProcessFields (TestContext testContext , BiConsumer <TestContextOverrideMetadata ,
88- BeanOverrideRegistrar > consumer ) {
89-
90- Class <?> testClass = testContext .getTestClass ();
91- Object testInstance = testContext .getTestInstance ();
92-
93- List <OverrideMetadata > metadataForFields = OverrideMetadata .forTestClass (testClass );
94- if (!metadataForFields .isEmpty ()) {
74+ /**
75+ * Inject each {@link BeanOverride @BeanOverride} field in the test instance with
76+ * a corresponding bean override instance.
77+ * <p>If the {@code reinjectFields} flag is {@code true} (which indicates that
78+ * a fresh instance is required), the field is nulled out before injecting
79+ * the overridden bean instance.
80+ */
81+ private static void injectFields (TestContext testContext , boolean reinjectFields ) {
82+ List <OverrideMetadata > overrideMetadataList = OverrideMetadata .forTestClass (testContext .getTestClass ());
83+ if (!overrideMetadataList .isEmpty ()) {
84+ Object testInstance = testContext .getTestInstance ();
9585 BeanOverrideRegistrar registrar = testContext .getApplicationContext ()
9686 .getBean (BeanOverrideContextCustomizer .REGISTRAR_BEAN_NAME , BeanOverrideRegistrar .class );
97- for (OverrideMetadata metadata : metadataForFields ) {
98- consumer .accept (new TestContextOverrideMetadata (testInstance , metadata ), registrar );
87+
88+ for (OverrideMetadata overrideMetadata : overrideMetadataList ) {
89+ if (reinjectFields ) {
90+ Field field = overrideMetadata .getField ();
91+ ReflectionUtils .makeAccessible (field );
92+ ReflectionUtils .setField (field , testInstance , null );
93+ }
94+ registrar .inject (testInstance , overrideMetadata );
9995 }
10096 }
10197 }
10298
103- private record TestContextOverrideMetadata (Object testInstance , OverrideMetadata overrideMetadata ) {}
104-
10599}
0 commit comments