Simplify and document BeanOverrideTestExecutionListener
This commit simplifies the implementation of BeanOverrideTestExecutionListener by introducing a static injectFields() utility method and removing the use of BiConsumers, records, and duplicated code. This commit also introduces Javadoc for all methods in BeanOverrideTestExecutionListener. Closes gh-33660
This commit is contained in:
parent
b0c7d15d9f
commit
28b9cf3b83
|
|
@ -18,7 +18,6 @@ package org.springframework.test.context.bean.override;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
|
|
@ -26,10 +25,12 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution
|
|||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@code TestExecutionListener} that enables Bean Override support in tests,
|
||||
* injecting overridden beans in appropriate fields of the test instance.
|
||||
* {@code TestExecutionListener} that enables {@link BeanOverride @BeanOverride}
|
||||
* support in tests, by injecting overridden beans in appropriate fields of the
|
||||
* test instance.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Sam Brannen
|
||||
* @since 6.2
|
||||
*/
|
||||
public class BeanOverrideTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
|
@ -42,64 +43,57 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
|
|||
return LOWEST_PRECEDENCE - 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject each {@link BeanOverride @BeanOverride} field in the
|
||||
* {@linkplain Object test instance} of the supplied {@linkplain TestContext
|
||||
* test context} with a corresponding bean override instance.
|
||||
*/
|
||||
@Override
|
||||
public void prepareTestInstance(TestContext testContext) throws Exception {
|
||||
injectFields(testContext);
|
||||
injectFields(testContext, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-inject each {@link BeanOverride @BeanOverride} field in the
|
||||
* {@linkplain Object test instance} of the supplied {@linkplain TestContext
|
||||
* test context} with a corresponding bean override instance.
|
||||
* <p>This method does nothing if the
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
|
||||
* REINJECT_DEPENDENCIES_ATTRIBUTE} attribute is not present in the
|
||||
* {@code TestContext} with a value of {@link Boolean#TRUE}.
|
||||
*/
|
||||
@Override
|
||||
public void beforeTestMethod(TestContext testContext) throws Exception {
|
||||
reinjectFieldsIfNecessary(testContext);
|
||||
Object reinjectDependenciesAttribute = testContext.getAttribute(
|
||||
DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE);
|
||||
if (Boolean.TRUE.equals(reinjectDependenciesAttribute)) {
|
||||
injectFields(testContext, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the test instance and make sure that fields flagged for bean
|
||||
* overriding are injected with the overridden bean instance.
|
||||
* Inject each {@link BeanOverride @BeanOverride} field in the test instance with
|
||||
* a corresponding bean override instance.
|
||||
* <p>If the {@code reinjectFields} flag is {@code true} (which indicates that
|
||||
* a fresh instance is required), the field is nulled out before injecting
|
||||
* the overridden bean instance.
|
||||
*/
|
||||
protected void injectFields(TestContext testContext) {
|
||||
postProcessFields(testContext, (testMetadata, registrar) ->
|
||||
registrar.inject(testMetadata.testInstance, testMetadata.overrideMetadata));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the test instance and make sure that fields flagged for bean
|
||||
* overriding are injected with the overridden bean instance, if necessary.
|
||||
* <p>If a fresh instance is required, the field is nulled out and then
|
||||
* re-injected with the overridden bean instance.
|
||||
* <p>This method does nothing if the
|
||||
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
|
||||
* attribute is not present in the {@code TestContext} with a value of {@link Boolean#TRUE}.
|
||||
*/
|
||||
protected void reinjectFieldsIfNecessary(TestContext testContext) throws Exception {
|
||||
if (Boolean.TRUE.equals(
|
||||
testContext.getAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE))) {
|
||||
|
||||
postProcessFields(testContext, (testMetadata, registrar) -> {
|
||||
Object testInstance = testMetadata.testInstance;
|
||||
Field field = testMetadata.overrideMetadata.getField();
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
ReflectionUtils.setField(field, testInstance, null);
|
||||
registrar.inject(testInstance, testMetadata.overrideMetadata);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void postProcessFields(TestContext testContext, BiConsumer<TestContextOverrideMetadata,
|
||||
BeanOverrideRegistrar> consumer) {
|
||||
|
||||
Class<?> testClass = testContext.getTestClass();
|
||||
private static void injectFields(TestContext testContext, boolean reinjectFields) {
|
||||
List<OverrideMetadata> overrideMetadataList = OverrideMetadata.forTestClass(testContext.getTestClass());
|
||||
if (!overrideMetadataList.isEmpty()) {
|
||||
Object testInstance = testContext.getTestInstance();
|
||||
|
||||
List<OverrideMetadata> metadataForFields = OverrideMetadata.forTestClass(testClass);
|
||||
if (!metadataForFields.isEmpty()) {
|
||||
BeanOverrideRegistrar registrar = testContext.getApplicationContext()
|
||||
.getBean(BeanOverrideContextCustomizer.REGISTRAR_BEAN_NAME, BeanOverrideRegistrar.class);
|
||||
for (OverrideMetadata metadata : metadataForFields) {
|
||||
consumer.accept(new TestContextOverrideMetadata(testInstance, metadata), registrar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record TestContextOverrideMetadata(Object testInstance, OverrideMetadata overrideMetadata) {}
|
||||
for (OverrideMetadata overrideMetadata : overrideMetadataList) {
|
||||
if (reinjectFields) {
|
||||
Field field = overrideMetadata.getField();
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
ReflectionUtils.setField(field, testInstance, null);
|
||||
}
|
||||
registrar.inject(testInstance, overrideMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue