Skip to content

Commit d59991f

Browse files
committed
Revise contribution
See gh-34006
1 parent cf46f39 commit d59991f

File tree

5 files changed

+64
-40
lines changed

5 files changed

+64
-40
lines changed

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

+19-16
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
6868

6969
private static final BeanNameGenerator beanNameGenerator = DefaultBeanNameGenerator.INSTANCE;
7070

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-
7471
private final Set<BeanOverrideHandler> beanOverrideHandlers;
7572

7673
private final BeanOverrideRegistry beanOverrideRegistry;
@@ -172,9 +169,11 @@ private void replaceOrCreateBean(ConfigurableListableBeanFactory beanFactory, Be
172169
}
173170
else if (requireExistingBean) {
174171
Field field = handler.getField();
175-
throw new IllegalStateException(
176-
"Unable to replace bean: there is no bean with name '%s' and type %s%s."
177-
.formatted(beanName, handler.getBeanType(), requiredByField(field, handler.getBeanType())));
172+
throw new IllegalStateException("""
173+
Unable to replace bean: there is no bean with name '%s' and type %s%s. \
174+
If the bean is defined in a @Bean method, make sure the return type is the \
175+
most specific type possible (for example, the concrete implementation type)."""
176+
.formatted(beanName, handler.getBeanType(), requiredByField(field)));
178177
}
179178
// 4) We are creating a bean by-name with the provided beanName.
180179
}
@@ -261,7 +260,11 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH
261260
String message = "Unable to select a bean to wrap: ";
262261
int candidateCount = candidateNames.size();
263262
if (candidateCount == 0) {
264-
message += "there are no beans of type %s%s.".formatted(beanType, requiredByField(field, beanType));
263+
message += """
264+
there are no beans of type %s%s. \
265+
If the bean is defined in a @Bean method, make sure the return type is the \
266+
most specific type possible (for example, the concrete implementation type)."""
267+
.formatted(beanType, requiredByField(field));
265268
}
266269
else {
267270
message += "found %d beans of type %s%s: %s"
@@ -275,8 +278,10 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH
275278
// We are wrapping an existing bean by-name.
276279
Set<String> candidates = getExistingBeanNamesByType(beanFactory, handler, false);
277280
if (!candidates.contains(beanName)) {
278-
throw new IllegalStateException(
279-
"Unable to wrap bean: there is no bean with name '%s' and type %s%s."
281+
throw new IllegalStateException("""
282+
Unable to wrap bean: there is no bean with name '%s' and type %s%s. \
283+
If the bean is defined in a @Bean method, make sure the return type is the \
284+
most specific type possible (for example, the concrete implementation type)."""
280285
.formatted(beanName, beanType, requiredByField(field)));
281286
}
282287
}
@@ -301,9 +306,11 @@ private static String getBeanNameForType(ConfigurableListableBeanFactory beanFac
301306
int candidateCount = candidateNames.size();
302307
if (candidateCount == 0) {
303308
if (requireExistingBean) {
304-
throw new IllegalStateException(
305-
"Unable to override bean: there are no beans of type %s%s."
306-
.formatted(beanType, requiredByField(field, beanType)));
309+
throw new IllegalStateException("""
310+
Unable to override bean: there are no beans of type %s%s. \
311+
If the bean is defined in a @Bean method, make sure the return type is the \
312+
most specific type possible (for example, the concrete implementation type)."""
313+
.formatted(beanType, requiredByField(field)));
307314
}
308315
return null;
309316
}
@@ -487,8 +494,4 @@ private static String requiredByField(@Nullable Field field) {
487494
field.getDeclaringClass().getSimpleName(), field.getName());
488495
}
489496

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

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

+12-6
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,11 @@ void replaceBeanByNameWithoutMatchingBeanDefinitionFails() {
8585

8686
assertThatIllegalStateException()
8787
.isThrownBy(context::refresh)
88-
.withMessageStartingWith("""
88+
.withMessage("""
8989
Unable to replace bean: there is no bean with name 'descriptionBean' \
90-
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
90+
and type java.lang.String (as required by field 'ByNameTestCase.description'). \
91+
If the bean is defined in a @Bean method, make sure the return type is the most \
92+
specific type possible (for example, the concrete implementation type).""");
9193
}
9294

9395
@Test
@@ -97,9 +99,11 @@ void replaceBeanByNameWithMatchingBeanDefinitionAndWrongTypeFails() {
9799

98100
assertThatIllegalStateException()
99101
.isThrownBy(context::refresh)
100-
.withMessageStartingWith("""
102+
.withMessage("""
101103
Unable to replace bean: there is no bean with name 'descriptionBean' \
102-
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
104+
and type java.lang.String (as required by field 'ByNameTestCase.description'). \
105+
If the bean is defined in a @Bean method, make sure the return type is the most \
106+
specific type possible (for example, the concrete implementation type).""");
103107
}
104108

105109
@Test
@@ -144,9 +148,11 @@ void replaceBeanByTypeWithoutMatchingBeanFails() {
144148

145149
assertThatIllegalStateException()
146150
.isThrownBy(context::refresh)
147-
.withMessageStartingWith("""
151+
.withMessage("""
148152
Unable to override bean: there are no beans of type java.lang.Integer \
149-
(as required by field 'ByTypeTestCase.counter').""");
153+
(as required by field 'ByTypeTestCase.counter'). \
154+
If the bean is defined in a @Bean method, make sure the return type is the most \
155+
specific type possible (for example, the concrete implementation type).""");
150156
}
151157

152158
@Test

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

+12-7
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4040
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
4141
assertThatIllegalStateException()
4242
.isThrownBy(context::refresh)
43-
.withMessageStartingWith("""
43+
.withMessage("""
4444
Unable to replace bean: there is no bean with name 'beanToOverride' \
45-
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
45+
and type java.lang.String (as required by field 'FailureByNameLookup.example'). \
46+
If the bean is defined in a @Bean method, make sure the return type is the most \
47+
specific type possible (for example, the concrete implementation type).""");
4648
}
4749

4850
@Test
@@ -52,9 +54,11 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5254
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
5355
assertThatIllegalStateException()
5456
.isThrownBy(context::refresh)
55-
.withMessageStartingWith("""
57+
.withMessage("""
5658
Unable to replace bean: there is no bean with name 'beanToOverride' \
57-
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
59+
and type java.lang.String (as required by field 'FailureByNameLookup.example'). \
60+
If the bean is defined in a @Bean method, make sure the return type is the most \
61+
specific type possible (for example, the concrete implementation type).""");
5862
}
5963

6064
@Test
@@ -63,9 +67,10 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6367
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByTypeLookup.class, context);
6468
assertThatIllegalStateException()
6569
.isThrownBy(context::refresh)
66-
.withMessageStartingWith("""
67-
Unable to override bean: there are no beans of \
68-
type %s (as required by field '%s.example').""",
70+
.withMessage("""
71+
Unable to override bean: there are no beans of type %s (as required by field '%s.example'). \
72+
If the bean is defined in a @Bean method, make sure the return type is the most \
73+
specific type possible (for example, the concrete implementation type).""",
6974
String.class.getName(), FailureByTypeLookup.class.getSimpleName());
7075
}
7176

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

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,9 +40,11 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4040
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
4141
assertThatIllegalStateException()
4242
.isThrownBy(context::refresh)
43-
.withMessageStartingWith("""
43+
.withMessage("""
4444
Unable to replace bean: there is no bean with name 'beanToOverride' \
45-
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
45+
and type java.lang.String (as required by field 'FailureByNameLookup.example'). \
46+
If the bean is defined in a @Bean method, make sure the return type is the most \
47+
specific type possible (for example, the concrete implementation type).""");
4648
}
4749

4850
@Test
@@ -52,9 +54,11 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5254
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByNameLookup.class, context);
5355
assertThatIllegalStateException()
5456
.isThrownBy(context::refresh)
55-
.withMessageStartingWith("""
57+
.withMessage("""
5658
Unable to replace bean: there is no bean with name 'beanToOverride' \
57-
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
59+
and type java.lang.String (as required by field 'FailureByNameLookup.example'). \
60+
If the bean is defined in a @Bean method, make sure the return type is the most \
61+
specific type possible (for example, the concrete implementation type).""");
5862
}
5963

6064
@Test
@@ -63,9 +67,11 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6367
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(FailureByTypeLookup.class, context);
6468
assertThatIllegalStateException()
6569
.isThrownBy(context::refresh)
66-
.withMessageStartingWith("""
70+
.withMessage("""
6771
Unable to override bean: there are no beans of \
68-
type java.lang.String (as required by field 'FailureByTypeLookup.example').""");
72+
type java.lang.String (as required by field 'FailureByTypeLookup.example'). \
73+
If the bean is defined in a @Bean method, make sure the return type is the most \
74+
specific type possible (for example, the concrete implementation type).""");
6975
}
7076

7177
@Test

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,7 +41,9 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanName() {
4141
.isThrownBy(context::refresh)
4242
.withMessage("""
4343
Unable to wrap bean: there is no bean with name 'beanToSpy' and \
44-
type java.lang.String (as required by field 'ByNameSingleLookup.example').""");
44+
type java.lang.String (as required by field 'ByNameSingleLookup.example'). \
45+
If the bean is defined in a @Bean method, make sure the return type is the most \
46+
specific type possible (for example, the concrete implementation type).""");
4547
}
4648

4749
@Test
@@ -50,9 +52,11 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
5052
BeanOverrideContextCustomizerTestUtils.customizeApplicationContext(ByTypeSingleLookup.class, context);
5153
assertThatIllegalStateException()
5254
.isThrownBy(context::refresh)
53-
.withMessageStartingWith("""
55+
.withMessage("""
5456
Unable to select a bean to wrap: there are no beans of type java.lang.String \
55-
(as required by field 'ByTypeSingleLookup.example').""");
57+
(as required by field 'ByTypeSingleLookup.example'). \
58+
If the bean is defined in a @Bean method, make sure the return type is the most \
59+
specific type possible (for example, the concrete implementation type).""");
5660
}
5761

5862
@Test

0 commit comments

Comments
 (0)