Construct consistent error messages in BeanOverrideBeanFactoryPostProcessor
This commit is contained in:
@@ -124,6 +124,7 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
// 3) AOT runtime
|
// 3) AOT runtime
|
||||||
|
|
||||||
String beanName = handler.getBeanName();
|
String beanName = handler.getBeanName();
|
||||||
|
Field field = handler.getField();
|
||||||
BeanDefinition existingBeanDefinition = null;
|
BeanDefinition existingBeanDefinition = null;
|
||||||
if (beanName == null) {
|
if (beanName == null) {
|
||||||
beanName = getBeanNameForType(beanFactory, handler, requireExistingBean);
|
beanName = getBeanNameForType(beanFactory, handler, requireExistingBean);
|
||||||
@@ -150,9 +151,10 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
}
|
}
|
||||||
else if (requireExistingBean) {
|
else if (requireExistingBean) {
|
||||||
throw new IllegalStateException("""
|
throw new IllegalStateException("""
|
||||||
Unable to override bean: there is no bean to replace \
|
Unable to replace bean: there is no bean with name '%s' and type %s \
|
||||||
with name [%s] and type [%s]."""
|
(as required by field '%s.%s')."""
|
||||||
.formatted(beanName, handler.getBeanType()));
|
.formatted(beanName, handler.getBeanType(),
|
||||||
|
field.getDeclaringClass().getSimpleName(), field.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +181,7 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
|
|
||||||
if (!(beanFactory instanceof BeanDefinitionRegistry registry)) {
|
if (!(beanFactory instanceof BeanDefinitionRegistry registry)) {
|
||||||
throw new IllegalStateException("Cannot process bean override with a BeanFactory " +
|
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);
|
RootBeanDefinition pseudoBeanDefinition = createPseudoBeanDefinition(handler);
|
||||||
@@ -220,6 +222,7 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
*/
|
*/
|
||||||
private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideHandler handler) {
|
private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideHandler handler) {
|
||||||
String beanName = handler.getBeanName();
|
String beanName = handler.getBeanName();
|
||||||
|
Field field = handler.getField();
|
||||||
ResolvableType beanType = handler.getBeanType();
|
ResolvableType beanType = handler.getBeanType();
|
||||||
|
|
||||||
if (beanName == null) {
|
if (beanName == null) {
|
||||||
@@ -235,13 +238,17 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
beanName = primaryCandidate;
|
beanName = primaryCandidate;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Field field = handler.getField();
|
String message = "Unable to select a bean to wrap: ";
|
||||||
throw new IllegalStateException("""
|
if (candidateCount == 0) {
|
||||||
Unable to select a bean to override by wrapping: found %d bean instances of type %s \
|
message += "there are no beans of type %s (as required by field '%s.%s')."
|
||||||
(as required by annotated field '%s.%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(),
|
.formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(),
|
||||||
field.getName(), (candidateCount > 0 ? ": " + candidateNames : "")));
|
field.getName(), candidateNames);
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
beanName = BeanFactoryUtils.transformedBeanName(beanName);
|
beanName = BeanFactoryUtils.transformedBeanName(beanName);
|
||||||
@@ -251,9 +258,10 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
Set<String> candidates = getExistingBeanNamesByType(beanFactory, handler, false);
|
Set<String> candidates = getExistingBeanNamesByType(beanFactory, handler, false);
|
||||||
if (!candidates.contains(beanName)) {
|
if (!candidates.contains(beanName)) {
|
||||||
throw new IllegalStateException("""
|
throw new IllegalStateException("""
|
||||||
Unable to override bean by wrapping: there is no existing bean \
|
Unable to wrap bean: there is no bean with name '%s' and type %s \
|
||||||
with name [%s] and type [%s]."""
|
(as required by field '%s.%s')."""
|
||||||
.formatted(beanName, beanType));
|
.formatted(beanName, beanType, field.getDeclaringClass().getSimpleName(),
|
||||||
|
field.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +284,7 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
else if (candidateCount == 0) {
|
else if (candidateCount == 0) {
|
||||||
if (requireExistingBean) {
|
if (requireExistingBean) {
|
||||||
throw new IllegalStateException(
|
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()));
|
.formatted(beanType, field.getDeclaringClass().getSimpleName(), field.getName()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -287,9 +295,8 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
return primaryCandidate;
|
return primaryCandidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("""
|
throw new IllegalStateException(
|
||||||
Unable to select a bean to override: found %s beans of type %s \
|
"Unable to select a bean to override: found %d beans of type %s (as required by field '%s.%s'): %s"
|
||||||
(as required by annotated field '%s.%s'): %s"""
|
|
||||||
.formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(),
|
.formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(),
|
||||||
field.getName(), candidateNames));
|
field.getName(), candidateNames));
|
||||||
}
|
}
|
||||||
@@ -416,7 +423,7 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
|||||||
private static void destroySingleton(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
private static void destroySingleton(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||||
if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
|
if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
|
||||||
throw new IllegalStateException("Cannot process bean override with a BeanFactory " +
|
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);
|
dlbf.destroySingleton(beanName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.springframework.test.context.bean.override;
|
|||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
@@ -84,8 +85,9 @@ class BeanOverrideBeanFactoryPostProcessorTests {
|
|||||||
|
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("Unable to override bean: there is no bean " +
|
.withMessage("""
|
||||||
"to replace with name [descriptionBean] and type [java.lang.String].");
|
Unable to replace bean: there is no bean with name 'descriptionBean' \
|
||||||
|
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -95,8 +97,9 @@ class BeanOverrideBeanFactoryPostProcessorTests {
|
|||||||
|
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("Unable to override bean: there is no bean " +
|
.withMessage("""
|
||||||
"to replace with name [descriptionBean] and type [java.lang.String].");
|
Unable to replace bean: there is no bean with name 'descriptionBean' \
|
||||||
|
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -141,8 +144,9 @@ class BeanOverrideBeanFactoryPostProcessorTests {
|
|||||||
|
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("Unable to override bean: no beans of type java.lang.Integer " +
|
.withMessage("""
|
||||||
"(as required by annotated field 'ByTypeTestCase.counter')");
|
Unable to override bean: there are no beans of type java.lang.Integer \
|
||||||
|
(as required by field 'ByTypeTestCase.counter').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -153,9 +157,10 @@ class BeanOverrideBeanFactoryPostProcessorTests {
|
|||||||
|
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("Unable to select a bean to override: found 2 beans " +
|
.withMessage("""
|
||||||
"of type java.lang.Integer (as required by annotated field 'ByTypeTestCase.counter'): " +
|
Unable to select a bean to override: found 2 beans of type java.lang.Integer \
|
||||||
"[someInteger, anotherInteger]");
|
(as required by field 'ByTypeTestCase.counter'): %s""",
|
||||||
|
List.of("someInteger", "anotherInteger"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public class TestBeanTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: there is no bean \
|
Unable to replace bean: there is no bean with name 'beanToOverride' \
|
||||||
to replace with name [beanToOverride] and type [java.lang.String].""");
|
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -52,8 +52,8 @@ public class TestBeanTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: there is no bean \
|
Unable to replace bean: there is no bean with name 'beanToOverride' \
|
||||||
to replace with name [beanToOverride] and type [java.lang.String].""");
|
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -63,8 +63,8 @@ public class TestBeanTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: no beans of \
|
Unable to override bean: there are no beans of \
|
||||||
type %s (as required by annotated field '%s.example')""".formatted(
|
type %s (as required by field '%s.example').""".formatted(
|
||||||
String.class.getName(), FailureByTypeLookup.class.getSimpleName()));
|
String.class.getName(), FailureByTypeLookup.class.getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +77,8 @@ public class TestBeanTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to select a bean to override: found 2 beans \
|
Unable to select a bean to override: found 2 beans of type java.lang.String \
|
||||||
of type %s (as required by annotated field '%s.example'): %s""".formatted(
|
(as required by field 'FailureByTypeLookup.example'): %s""", List.of("bean1", "bean2"));
|
||||||
String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class MockitoBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: there is no bean \
|
Unable to replace bean: there is no bean with name 'beanToOverride' \
|
||||||
to replace with name [beanToOverride] and type [java.lang.String].""");
|
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -53,8 +53,8 @@ class MockitoBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: there is no bean \
|
Unable to replace bean: there is no bean with name 'beanToOverride' \
|
||||||
to replace with name [beanToOverride] and type [java.lang.String].""");
|
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -64,9 +64,8 @@ class MockitoBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean: no beans of \
|
Unable to override bean: there are no beans of \
|
||||||
type %s (as required by annotated field '%s.example')""".formatted(
|
type java.lang.String (as required by field 'FailureByTypeLookup.example').""");
|
||||||
String.class.getName(), FailureByTypeLookup.class.getSimpleName()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -78,9 +77,9 @@ class MockitoBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to select a bean to override: found 2 beans \
|
Unable to select a bean to override: found 2 beans of type java.lang.String \
|
||||||
of type %s (as required by annotated field '%s.example'): %s""".formatted(
|
(as required by field 'FailureByTypeLookup.example'): %s""",
|
||||||
String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2")));
|
List.of("bean1", "bean2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,9 @@ class MockitoSpyBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to override bean by wrapping: \
|
Unable to wrap bean: there is no bean with name 'beanToSpy' and \
|
||||||
there is no existing bean with name [beanToSpy] and type [%s].""",
|
type java.lang.String (as required by field 'ByNameSingleLookup.example').""");
|
||||||
String.class.getName());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
|
void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
|
||||||
@@ -52,9 +51,8 @@ class MockitoSpyBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to select a bean to override by wrapping: found 0 bean instances of \
|
Unable to select a bean to wrap: there are no beans of type java.lang.String \
|
||||||
type %s (as required by annotated field '%s.example')""",
|
(as required by field 'ByTypeSingleLookup.example').""");
|
||||||
String.class.getName(), ByTypeSingleLookup.class.getSimpleName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -66,9 +64,9 @@ class MockitoSpyBeanConfigurationErrorTests {
|
|||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(context::refresh)
|
.isThrownBy(context::refresh)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
Unable to select a bean to override by wrapping: found 2 bean instances \
|
Unable to select a bean to wrap: found 2 beans of type java.lang.String \
|
||||||
of type %s (as required by annotated field '%s.example'): %s""",
|
(as required by field 'ByTypeSingleLookup.example'): %s""",
|
||||||
String.class.getName(), ByTypeSingleLookup.class.getSimpleName(), List.of("bean1", "bean2"));
|
List.of("bean1", "bean2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user