Skip to content

Commit c6fa286

Browse files
committed
Improve diagnostics when a Bean Override cannot be selected by type
Close GH-34004 Signed-off-by: Yanming Zhou <[email protected]>
1 parent 6113869 commit c6fa286

File tree

5 files changed

+21
-13
lines changed

5 files changed

+21
-13
lines changed

spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
* @author Simon Baslé
6060
* @author Stephane Nicoll
6161
* @author Sam Brannen
62+
* @author Yanming Zhou
6263
* @since 6.2
6364
*/
6465
class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {
@@ -67,6 +68,9 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
6768

6869
private static final BeanNameGenerator beanNameGenerator = DefaultBeanNameGenerator.INSTANCE;
6970

71+
private static final String unableToOverrideByTypeDiagnosticsMessage = " If the bean is defined from a @Bean method,"
72+
+ " please make sure the return type is the most specific type (recommended) or type can be assigned to %s.";
73+
7074
private final Set<BeanOverrideHandler> beanOverrideHandlers;
7175

7276
private final BeanOverrideRegistry beanOverrideRegistry;
@@ -170,7 +174,7 @@ else if (requireExistingBean) {
170174
Field field = handler.getField();
171175
throw new IllegalStateException(
172176
"Unable to replace bean: there is no bean with name '%s' and type %s%s."
173-
.formatted(beanName, handler.getBeanType(), requiredByField(field)));
177+
.formatted(beanName, handler.getBeanType(), requiredByField(field, handler.getBeanType())));
174178
}
175179
// 4) We are creating a bean by-name with the provided beanName.
176180
}
@@ -257,7 +261,7 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH
257261
String message = "Unable to select a bean to wrap: ";
258262
int candidateCount = candidateNames.size();
259263
if (candidateCount == 0) {
260-
message += "there are no beans of type %s%s.".formatted(beanType, requiredByField(field));
264+
message += "there are no beans of type %s%s.".formatted(beanType, requiredByField(field, beanType));
261265
}
262266
else {
263267
message += "found %d beans of type %s%s: %s"
@@ -299,7 +303,7 @@ private static String getBeanNameForType(ConfigurableListableBeanFactory beanFac
299303
if (requireExistingBean) {
300304
throw new IllegalStateException(
301305
"Unable to override bean: there are no beans of type %s%s."
302-
.formatted(beanType, requiredByField(field)));
306+
.formatted(beanType, requiredByField(field, beanType)));
303307
}
304308
return null;
305309
}
@@ -483,4 +487,8 @@ private static String requiredByField(@Nullable Field field) {
483487
field.getDeclaringClass().getSimpleName(), field.getName());
484488
}
485489

490+
private static String requiredByField(@Nullable Field field, ResolvableType requiredBeanType) {
491+
return requiredByField(field) + unableToOverrideByTypeDiagnosticsMessage.formatted(requiredBeanType);
492+
}
493+
486494
}

spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ void replaceBeanByNameWithoutMatchingBeanDefinitionFails() {
8585

8686
assertThatIllegalStateException()
8787
.isThrownBy(context::refresh)
88-
.withMessage("""
88+
.withMessageStartingWith("""
8989
Unable to replace bean: there is no bean with name 'descriptionBean' \
9090
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
9191
}
@@ -97,7 +97,7 @@ void replaceBeanByNameWithMatchingBeanDefinitionAndWrongTypeFails() {
9797

9898
assertThatIllegalStateException()
9999
.isThrownBy(context::refresh)
100-
.withMessage("""
100+
.withMessageStartingWith("""
101101
Unable to replace bean: there is no bean with name 'descriptionBean' \
102102
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
103103
}
@@ -144,7 +144,7 @@ void replaceBeanByTypeWithoutMatchingBeanFails() {
144144

145145
assertThatIllegalStateException()
146146
.isThrownBy(context::refresh)
147-
.withMessage("""
147+
.withMessageStartingWith("""
148148
Unable to override bean: there are no beans of type java.lang.Integer \
149149
(as required by field 'ByTypeTestCase.counter').""");
150150
}

spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4040
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
4141
assertThatIllegalStateException()
4242
.isThrownBy(context::refresh)
43-
.withMessage("""
43+
.withMessageStartingWith("""
4444
Unable to replace bean: there is no bean with name 'beanToOverride' \
4545
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
4646
}
@@ -52,7 +52,7 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5252
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
5353
assertThatIllegalStateException()
5454
.isThrownBy(context::refresh)
55-
.withMessage("""
55+
.withMessageStartingWith("""
5656
Unable to replace bean: there is no bean with name 'beanToOverride' \
5757
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
5858
}
@@ -63,7 +63,7 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6363
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByTypeLookup.class, context);
6464
assertThatIllegalStateException()
6565
.isThrownBy(context::refresh)
66-
.withMessage("""
66+
.withMessageStartingWith("""
6767
Unable to override bean: there are no beans of \
6868
type %s (as required by field '%s.example').""",
6969
String.class.getName(), FailureByTypeLookup.class.getSimpleName());

spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanConfigurationErrorTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4040
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
4141
assertThatIllegalStateException()
4242
.isThrownBy(context::refresh)
43-
.withMessage("""
43+
.withMessageStartingWith("""
4444
Unable to replace bean: there is no bean with name 'beanToOverride' \
4545
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
4646
}
@@ -52,7 +52,7 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5252
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
5353
assertThatIllegalStateException()
5454
.isThrownBy(context::refresh)
55-
.withMessage("""
55+
.withMessageStartingWith("""
5656
Unable to replace bean: there is no bean with name 'beanToOverride' \
5757
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
5858
}
@@ -63,7 +63,7 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6363
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByTypeLookup.class, context);
6464
assertThatIllegalStateException()
6565
.isThrownBy(context::refresh)
66-
.withMessage("""
66+
.withMessageStartingWith("""
6767
Unable to override bean: there are no beans of \
6868
type java.lang.String (as required by field 'FailureByTypeLookup.example').""");
6969
}

spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanConfigurationErrorTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
5050
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(ByTypeSingleLookup.class, context);
5151
assertThatIllegalStateException()
5252
.isThrownBy(context::refresh)
53-
.withMessage("""
53+
.withMessageStartingWith("""
5454
Unable to select a bean to wrap: there are no beans of type java.lang.String \
5555
(as required by field 'ByTypeSingleLookup.example').""");
5656
}

0 commit comments

Comments
 (0)