Polish TestBeanOverrideProcessor

This commit is contained in:
Sam Brannen
2024-06-03 13:29:50 +02:00
parent f7e7d1b7b0
commit 8047a22237

View File

@@ -21,6 +21,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
@@ -40,7 +41,7 @@ import org.springframework.util.StringUtils;
/**
* {@link BeanOverrideProcessor} implementation for {@link TestBean @TestBean}
* support. It creates metadata for annotated fields in a given class and
* support, which creates metadata for annotated fields in a given class and
* ensures that a corresponding static factory method exists, according to the
* {@linkplain TestBean documented conventions}.
*
@@ -50,6 +51,15 @@ import org.springframework.util.StringUtils;
*/
class TestBeanOverrideProcessor implements BeanOverrideProcessor {
/**
* Find a test bean factory {@link Method} in the given {@link Class} or one
* of its parent classes.
* <p>Delegates to {@link #findTestBeanFactoryMethod(Class, Class, List)}.
*/
static Method findTestBeanFactoryMethod(Class<?> clazz, Class<?> methodReturnType, String... methodNames) {
return findTestBeanFactoryMethod(clazz, methodReturnType, List.of(methodNames));
}
/**
* Find a test bean factory {@link Method} in the given {@link Class} or one
* of its parent classes, which meets the following criteria.
@@ -61,7 +71,7 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
* </ul>
* <p>If the test class inherits from another class, the class hierarchy is
* searched for factory methods. Matching factory methods are prioritized
* from closest to furthest from the test class in the class hierarchy,
* from closest to farthest from the test class in the class hierarchy,
* provided they have the same name. However, if multiple methods are found
* that match distinct candidate names, an exception is thrown.
* @param clazz the class in which to search for the factory method
@@ -71,9 +81,9 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
* @throws IllegalStateException if a matching factory method cannot
* be found or multiple methods match
*/
static Method findTestBeanFactoryMethod(Class<?> clazz, Class<?> methodReturnType, String... methodNames) {
Assert.isTrue(methodNames.length > 0, "At least one candidate method name is required");
Set<String> supportedNames = new LinkedHashSet<>(Arrays.asList(methodNames));
static Method findTestBeanFactoryMethod(Class<?> clazz, Class<?> methodReturnType, List<String> methodNames) {
Assert.notEmpty(methodNames, "At least one candidate method name is required");
Set<String> supportedNames = new LinkedHashSet<>(methodNames);
List<Method> methods = Arrays.stream(ReflectionUtils.getAllDeclaredMethods(clazz))
.filter(method -> Modifier.isStatic(method.getModifiers()) &&
supportedNames.contains(method.getName()) &&
@@ -110,27 +120,26 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
TestBeanOverrideProcessor.class.getSimpleName(), field.getDeclaringClass().getName(),
field.getName()));
}
// If the user specified a method explicitly, search for that.
// Otherwise, search candidate factory methods using the convention suffix
// and the explicit bean name (if any) or field name.
Method explicitOverrideMethod;
if (!testBeanAnnotation.methodName().isBlank()) {
explicitOverrideMethod = findTestBeanFactoryMethod(testClass, field.getType(), testBeanAnnotation.methodName());
Method overrideMethod;
String methodName = testBeanAnnotation.methodName();
if (!methodName.isBlank()) {
// If the user specified an explicit method name, search for that.
overrideMethod = findTestBeanFactoryMethod(testClass, field.getType(), methodName);
}
else {
// Otherwise, search for candidate factory methods using the convention
// suffix and the field name or explicit bean name (if any).
List<String> candidateMethodNames = new ArrayList<>();
candidateMethodNames.add(field.getName() + TestBean.CONVENTION_SUFFIX);
String beanName = testBeanAnnotation.name();
if (!StringUtils.hasText(beanName)) {
explicitOverrideMethod = findTestBeanFactoryMethod(testClass, field.getType(),
field.getName() + TestBean.CONVENTION_SUFFIX);
}
else {
explicitOverrideMethod = findTestBeanFactoryMethod(testClass, field.getType(),
beanName + TestBean.CONVENTION_SUFFIX,
field.getName() + TestBean.CONVENTION_SUFFIX);
if (StringUtils.hasText(beanName)) {
candidateMethodNames.add(beanName + TestBean.CONVENTION_SUFFIX);
}
overrideMethod = findTestBeanFactoryMethod(testClass, field.getType(), candidateMethodNames);
}
return new TestBeanOverrideMetadata(field, explicitOverrideMethod, testBeanAnnotation, ResolvableType.forField(field, testClass));
return new TestBeanOverrideMetadata(field, overrideMethod, testBeanAnnotation, ResolvableType.forField(field, testClass));
}