From 8047a2223701ee03a93c715d0fd6be4bb870a4e3 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:29:50 +0200 Subject: [PATCH] Polish TestBeanOverrideProcessor --- .../convention/TestBeanOverrideProcessor.java | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideProcessor.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideProcessor.java index 8ce8f56ac5..457acf75c1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideProcessor.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideProcessor.java @@ -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. + *

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 { * *

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 supportedNames = new LinkedHashSet<>(Arrays.asList(methodNames)); + static Method findTestBeanFactoryMethod(Class clazz, Class methodReturnType, List methodNames) { + Assert.notEmpty(methodNames, "At least one candidate method name is required"); + Set supportedNames = new LinkedHashSet<>(methodNames); List 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 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)); }