diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java index 32db0408cb04..4be7503b6f3e 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java @@ -124,6 +124,7 @@ private void replaceOrCreateBean(ConfigurableListableBeanFactory beanFactory, Be // 3) AOT runtime String beanName = handler.getBeanName(); + Field field = handler.getField(); BeanDefinition existingBeanDefinition = null; if (beanName == null) { beanName = getBeanNameForType(beanFactory, handler, requireExistingBean); @@ -150,9 +151,10 @@ private void replaceOrCreateBean(ConfigurableListableBeanFactory beanFactory, Be } else if (requireExistingBean) { throw new IllegalStateException(""" - Unable to override bean: there is no bean to replace \ - with name [%s] and type [%s].""" - .formatted(beanName, handler.getBeanType())); + Unable to replace bean: there is no bean with name '%s' and type %s \ + (as required by field '%s.%s').""" + .formatted(beanName, handler.getBeanType(), + field.getDeclaringClass().getSimpleName(), field.getName())); } } @@ -179,7 +181,7 @@ else if (Boolean.getBoolean(AbstractAotProcessor.AOT_PROCESSING)) { if (!(beanFactory instanceof BeanDefinitionRegistry registry)) { throw new IllegalStateException("Cannot process bean override with a BeanFactory " + - "that doesn't implement BeanDefinitionRegistry: " + beanFactory.getClass().getName()); + "that does not implement BeanDefinitionRegistry: " + beanFactory.getClass().getName()); } RootBeanDefinition pseudoBeanDefinition = createPseudoBeanDefinition(handler); @@ -220,6 +222,7 @@ else if (Boolean.getBoolean(AbstractAotProcessor.AOT_PROCESSING)) { */ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideHandler handler) { String beanName = handler.getBeanName(); + Field field = handler.getField(); ResolvableType beanType = handler.getBeanType(); if (beanName == null) { @@ -235,13 +238,17 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH beanName = primaryCandidate; } else { - Field field = handler.getField(); - throw new IllegalStateException(""" - Unable to select a bean to override by wrapping: found %d bean instances of type %s \ - (as required by annotated field '%s.%s')%s""" + String message = "Unable to select a bean to wrap: "; + if (candidateCount == 0) { + message += "there are no beans of type %s (as required by field '%s.%s')." + .formatted(beanType, field.getDeclaringClass().getSimpleName(), field.getName()); + } + else { + message += "found %d beans of type %s (as required by field '%s.%s'): %s" .formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(), - field.getName(), (candidateCount > 0 ? ": " + candidateNames : ""))); - + field.getName(), candidateNames); + } + throw new IllegalStateException(message); } } beanName = BeanFactoryUtils.transformedBeanName(beanName); @@ -251,9 +258,10 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH Set candidates = getExistingBeanNamesByType(beanFactory, handler, false); if (!candidates.contains(beanName)) { throw new IllegalStateException(""" - Unable to override bean by wrapping: there is no existing bean \ - with name [%s] and type [%s].""" - .formatted(beanName, beanType)); + Unable to wrap bean: there is no bean with name '%s' and type %s \ + (as required by field '%s.%s').""" + .formatted(beanName, beanType, field.getDeclaringClass().getSimpleName(), + field.getName())); } } @@ -276,7 +284,7 @@ private String getBeanNameForType(ConfigurableListableBeanFactory beanFactory, B else if (candidateCount == 0) { if (requireExistingBean) { throw new IllegalStateException( - "Unable to override bean: no beans of type %s (as required by annotated field '%s.%s')" + "Unable to override bean: there are no beans of type %s (as required by field '%s.%s')." .formatted(beanType, field.getDeclaringClass().getSimpleName(), field.getName())); } return null; @@ -287,9 +295,8 @@ else if (candidateCount == 0) { return primaryCandidate; } - throw new IllegalStateException(""" - Unable to select a bean to override: found %s beans of type %s \ - (as required by annotated field '%s.%s'): %s""" + throw new IllegalStateException( + "Unable to select a bean to override: found %d beans of type %s (as required by field '%s.%s'): %s" .formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(), field.getName(), candidateNames)); } @@ -416,7 +423,7 @@ private static void validateBeanDefinition(ConfigurableListableBeanFactory beanF private static void destroySingleton(ConfigurableListableBeanFactory beanFactory, String beanName) { if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) { throw new IllegalStateException("Cannot process bean override with a BeanFactory " + - "that doesn't implement DefaultListableBeanFactory: " + beanFactory.getClass().getName()); + "that does not implement DefaultListableBeanFactory: " + beanFactory.getClass().getName()); } dlbf.destroySingleton(beanName); } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java index cf6c38e553ff..a7e29a35a673 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java @@ -18,6 +18,7 @@ import java.lang.reflect.Field; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; @@ -84,8 +85,9 @@ void replaceBeanByNameWithoutMatchingBeanDefinitionFails() { assertThatIllegalStateException() .isThrownBy(context::refresh) - .withMessage("Unable to override bean: there is no bean " + - "to replace with name [descriptionBean] and type [java.lang.String]."); + .withMessage(""" + Unable to replace bean: there is no bean with name 'descriptionBean' \ + and type java.lang.String (as required by field 'ByNameTestCase.description')."""); } @Test @@ -95,8 +97,9 @@ void replaceBeanByNameWithMatchingBeanDefinitionAndWrongTypeFails() { assertThatIllegalStateException() .isThrownBy(context::refresh) - .withMessage("Unable to override bean: there is no bean " + - "to replace with name [descriptionBean] and type [java.lang.String]."); + .withMessage(""" + Unable to replace bean: there is no bean with name 'descriptionBean' \ + and type java.lang.String (as required by field 'ByNameTestCase.description')."""); } @Test @@ -141,8 +144,9 @@ void replaceBeanByTypeWithoutMatchingBeanFails() { assertThatIllegalStateException() .isThrownBy(context::refresh) - .withMessage("Unable to override bean: no beans of type java.lang.Integer " + - "(as required by annotated field 'ByTypeTestCase.counter')"); + .withMessage(""" + Unable to override bean: there are no beans of type java.lang.Integer \ + (as required by field 'ByTypeTestCase.counter')."""); } @Test @@ -153,9 +157,10 @@ void replaceBeanByTypeWithMultipleCandidatesAndNoQualifierFails() { assertThatIllegalStateException() .isThrownBy(context::refresh) - .withMessage("Unable to select a bean to override: found 2 beans " + - "of type java.lang.Integer (as required by annotated field 'ByTypeTestCase.counter'): " + - "[someInteger, anotherInteger]"); + .withMessage(""" + Unable to select a bean to override: found 2 beans of type java.lang.Integer \ + (as required by field 'ByTypeTestCase.counter'): %s""", + List.of("someInteger", "anotherInteger")); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanTests.java index 8a1063e53548..9685ed07179d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanTests.java @@ -40,8 +40,8 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: there is no bean \ - to replace with name [beanToOverride] and type [java.lang.String]."""); + Unable to replace bean: there is no bean with name 'beanToOverride' \ + and type java.lang.String (as required by field 'FailureByNameLookup.example')."""); } @Test @@ -52,8 +52,8 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: there is no bean \ - to replace with name [beanToOverride] and type [java.lang.String]."""); + Unable to replace bean: there is no bean with name 'beanToOverride' \ + and type java.lang.String (as required by field 'FailureByNameLookup.example')."""); } @Test @@ -63,8 +63,8 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: no beans of \ - type %s (as required by annotated field '%s.example')""".formatted( + Unable to override bean: there are no beans of \ + type %s (as required by field '%s.example').""".formatted( String.class.getName(), FailureByTypeLookup.class.getSimpleName())); } @@ -77,9 +77,8 @@ void cannotOverrideBeanByTypeWithTooManyBeansOfThatType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to select a bean to override: found 2 beans \ - of type %s (as required by annotated field '%s.example'): %s""".formatted( - String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2"))); + Unable to select a bean to override: found 2 beans of type java.lang.String \ + (as required by field 'FailureByTypeLookup.example'): %s""", List.of("bean1", "bean2")); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanConfigurationErrorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanConfigurationErrorTests.java index f9b9f920678d..1182a8afc59c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanConfigurationErrorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanConfigurationErrorTests.java @@ -41,8 +41,8 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: there is no bean \ - to replace with name [beanToOverride] and type [java.lang.String]."""); + Unable to replace bean: there is no bean with name 'beanToOverride' \ + and type java.lang.String (as required by field 'FailureByNameLookup.example')."""); } @Test @@ -53,8 +53,8 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: there is no bean \ - to replace with name [beanToOverride] and type [java.lang.String]."""); + Unable to replace bean: there is no bean with name 'beanToOverride' \ + and type java.lang.String (as required by field 'FailureByNameLookup.example')."""); } @Test @@ -64,9 +64,8 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean: no beans of \ - type %s (as required by annotated field '%s.example')""".formatted( - String.class.getName(), FailureByTypeLookup.class.getSimpleName())); + Unable to override bean: there are no beans of \ + type java.lang.String (as required by field 'FailureByTypeLookup.example')."""); } @Test @@ -78,9 +77,9 @@ void cannotOverrideBeanByTypeWithTooManyBeansOfThatType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to select a bean to override: found 2 beans \ - of type %s (as required by annotated field '%s.example'): %s""".formatted( - String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2"))); + Unable to select a bean to override: found 2 beans of type java.lang.String \ + (as required by field 'FailureByTypeLookup.example'): %s""", + List.of("bean1", "bean2")); } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanConfigurationErrorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanConfigurationErrorTests.java index 0d9933272c52..efdbf8873334 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanConfigurationErrorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanConfigurationErrorTests.java @@ -40,10 +40,9 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanName() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to override bean by wrapping: \ - there is no existing bean with name [beanToSpy] and type [%s].""", - String.class.getName()); - } + Unable to wrap bean: there is no bean with name 'beanToSpy' and \ + type java.lang.String (as required by field 'ByNameSingleLookup.example')."""); + } @Test void contextCustomizerCannotBeCreatedWithNoSuchBeanType() { @@ -52,9 +51,8 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to select a bean to override by wrapping: found 0 bean instances of \ - type %s (as required by annotated field '%s.example')""", - String.class.getName(), ByTypeSingleLookup.class.getSimpleName()); + Unable to select a bean to wrap: there are no beans of type java.lang.String \ + (as required by field 'ByTypeSingleLookup.example')."""); } @Test @@ -66,9 +64,9 @@ void contextCustomizerCannotBeCreatedWithTooManyBeansOfThatType() { assertThatIllegalStateException() .isThrownBy(context::refresh) .withMessage(""" - Unable to select a bean to override by wrapping: found 2 bean instances \ - of type %s (as required by annotated field '%s.example'): %s""", - String.class.getName(), ByTypeSingleLookup.class.getSimpleName(), List.of("bean1", "bean2")); + Unable to select a bean to wrap: found 2 beans of type java.lang.String \ + (as required by field 'ByTypeSingleLookup.example'): %s""", + List.of("bean1", "bean2")); }