Skip to content

Commit b9cf03f

Browse files
committed
Construct consistent error messages in BeanOverrideBeanFactoryPostProcessor
1 parent 08a789c commit b9cf03f

File tree

5 files changed

+64
-56
lines changed

5 files changed

+64
-56
lines changed

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

+25-18
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ private void replaceOrCreateBean(ConfigurableListableBeanFactory beanFactory, Be
124124
// 3) AOT runtime
125125

126126
String beanName = handler.getBeanName();
127+
Field field = handler.getField();
127128
BeanDefinition existingBeanDefinition = null;
128129
if (beanName == null) {
129130
beanName = getBeanNameForType(beanFactory, handler, requireExistingBean);
@@ -150,9 +151,10 @@ private void replaceOrCreateBean(ConfigurableListableBeanFactory beanFactory, Be
150151
}
151152
else if (requireExistingBean) {
152153
throw new IllegalStateException("""
153-
Unable to override bean: there is no bean to replace \
154-
with name [%s] and type [%s]."""
155-
.formatted(beanName, handler.getBeanType()));
154+
Unable to replace bean: there is no bean with name '%s' and type %s \
155+
(as required by field '%s.%s')."""
156+
.formatted(beanName, handler.getBeanType(),
157+
field.getDeclaringClass().getSimpleName(), field.getName()));
156158
}
157159
}
158160

@@ -179,7 +181,7 @@ else if (Boolean.getBoolean(AbstractAotProcessor.AOT_PROCESSING)) {
179181

180182
if (!(beanFactory instanceof BeanDefinitionRegistry registry)) {
181183
throw new IllegalStateException("Cannot process bean override with a BeanFactory " +
182-
"that doesn't implement BeanDefinitionRegistry: " + beanFactory.getClass().getName());
184+
"that does not implement BeanDefinitionRegistry: " + beanFactory.getClass().getName());
183185
}
184186

185187
RootBeanDefinition pseudoBeanDefinition = createPseudoBeanDefinition(handler);
@@ -220,6 +222,7 @@ else if (Boolean.getBoolean(AbstractAotProcessor.AOT_PROCESSING)) {
220222
*/
221223
private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideHandler handler) {
222224
String beanName = handler.getBeanName();
225+
Field field = handler.getField();
223226
ResolvableType beanType = handler.getBeanType();
224227

225228
if (beanName == null) {
@@ -235,13 +238,17 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH
235238
beanName = primaryCandidate;
236239
}
237240
else {
238-
Field field = handler.getField();
239-
throw new IllegalStateException("""
240-
Unable to select a bean to override by wrapping: found %d bean instances of type %s \
241-
(as required by annotated field '%s.%s')%s"""
241+
String message = "Unable to select a bean to wrap: ";
242+
if (candidateCount == 0) {
243+
message += "there are no beans of type %s (as required by field '%s.%s')."
244+
.formatted(beanType, field.getDeclaringClass().getSimpleName(), field.getName());
245+
}
246+
else {
247+
message += "found %d beans of type %s (as required by field '%s.%s'): %s"
242248
.formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(),
243-
field.getName(), (candidateCount > 0 ? ": " + candidateNames : "")));
244-
249+
field.getName(), candidateNames);
250+
}
251+
throw new IllegalStateException(message);
245252
}
246253
}
247254
beanName = BeanFactoryUtils.transformedBeanName(beanName);
@@ -251,9 +258,10 @@ private void wrapBean(ConfigurableListableBeanFactory beanFactory, BeanOverrideH
251258
Set<String> candidates = getExistingBeanNamesByType(beanFactory, handler, false);
252259
if (!candidates.contains(beanName)) {
253260
throw new IllegalStateException("""
254-
Unable to override bean by wrapping: there is no existing bean \
255-
with name [%s] and type [%s]."""
256-
.formatted(beanName, beanType));
261+
Unable to wrap bean: there is no bean with name '%s' and type %s \
262+
(as required by field '%s.%s')."""
263+
.formatted(beanName, beanType, field.getDeclaringClass().getSimpleName(),
264+
field.getName()));
257265
}
258266
}
259267

@@ -276,7 +284,7 @@ private String getBeanNameForType(ConfigurableListableBeanFactory beanFactory, B
276284
else if (candidateCount == 0) {
277285
if (requireExistingBean) {
278286
throw new IllegalStateException(
279-
"Unable to override bean: no beans of type %s (as required by annotated field '%s.%s')"
287+
"Unable to override bean: there are no beans of type %s (as required by field '%s.%s')."
280288
.formatted(beanType, field.getDeclaringClass().getSimpleName(), field.getName()));
281289
}
282290
return null;
@@ -287,9 +295,8 @@ else if (candidateCount == 0) {
287295
return primaryCandidate;
288296
}
289297

290-
throw new IllegalStateException("""
291-
Unable to select a bean to override: found %s beans of type %s \
292-
(as required by annotated field '%s.%s'): %s"""
298+
throw new IllegalStateException(
299+
"Unable to select a bean to override: found %d beans of type %s (as required by field '%s.%s'): %s"
293300
.formatted(candidateCount, beanType, field.getDeclaringClass().getSimpleName(),
294301
field.getName(), candidateNames));
295302
}
@@ -416,7 +423,7 @@ private static void validateBeanDefinition(ConfigurableListableBeanFactory beanF
416423
private static void destroySingleton(ConfigurableListableBeanFactory beanFactory, String beanName) {
417424
if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
418425
throw new IllegalStateException("Cannot process bean override with a BeanFactory " +
419-
"that doesn't implement DefaultListableBeanFactory: " + beanFactory.getClass().getName());
426+
"that does not implement DefaultListableBeanFactory: " + beanFactory.getClass().getName());
420427
}
421428
dlbf.destroySingleton(beanName);
422429
}

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

+14-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.lang.reflect.Field;
2020
import java.util.LinkedHashSet;
21+
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Set;
2324
import java.util.function.Predicate;
@@ -84,8 +85,9 @@ void replaceBeanByNameWithoutMatchingBeanDefinitionFails() {
8485

8586
assertThatIllegalStateException()
8687
.isThrownBy(context::refresh)
87-
.withMessage("Unable to override bean: there is no bean " +
88-
"to replace with name [descriptionBean] and type [java.lang.String].");
88+
.withMessage("""
89+
Unable to replace bean: there is no bean with name 'descriptionBean' \
90+
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
8991
}
9092

9193
@Test
@@ -95,8 +97,9 @@ void replaceBeanByNameWithMatchingBeanDefinitionAndWrongTypeFails() {
9597

9698
assertThatIllegalStateException()
9799
.isThrownBy(context::refresh)
98-
.withMessage("Unable to override bean: there is no bean " +
99-
"to replace with name [descriptionBean] and type [java.lang.String].");
100+
.withMessage("""
101+
Unable to replace bean: there is no bean with name 'descriptionBean' \
102+
and type java.lang.String (as required by field 'ByNameTestCase.description').""");
100103
}
101104

102105
@Test
@@ -141,8 +144,9 @@ void replaceBeanByTypeWithoutMatchingBeanFails() {
141144

142145
assertThatIllegalStateException()
143146
.isThrownBy(context::refresh)
144-
.withMessage("Unable to override bean: no beans of type java.lang.Integer " +
145-
"(as required by annotated field 'ByTypeTestCase.counter')");
147+
.withMessage("""
148+
Unable to override bean: there are no beans of type java.lang.Integer \
149+
(as required by field 'ByTypeTestCase.counter').""");
146150
}
147151

148152
@Test
@@ -153,9 +157,10 @@ void replaceBeanByTypeWithMultipleCandidatesAndNoQualifierFails() {
153157

154158
assertThatIllegalStateException()
155159
.isThrownBy(context::refresh)
156-
.withMessage("Unable to select a bean to override: found 2 beans " +
157-
"of type java.lang.Integer (as required by annotated field 'ByTypeTestCase.counter'): " +
158-
"[someInteger, anotherInteger]");
160+
.withMessage("""
161+
Unable to select a bean to override: found 2 beans of type java.lang.Integer \
162+
(as required by field 'ByTypeTestCase.counter'): %s""",
163+
List.of("someInteger", "anotherInteger"));
159164
}
160165

161166
@Test

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

+8-9
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4040
assertThatIllegalStateException()
4141
.isThrownBy(context::refresh)
4242
.withMessage("""
43-
Unable to override bean: there is no bean \
44-
to replace with name [beanToOverride] and type [java.lang.String].""");
43+
Unable to replace bean: there is no bean with name 'beanToOverride' \
44+
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
4545
}
4646

4747
@Test
@@ -52,8 +52,8 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5252
assertThatIllegalStateException()
5353
.isThrownBy(context::refresh)
5454
.withMessage("""
55-
Unable to override bean: there is no bean \
56-
to replace with name [beanToOverride] and type [java.lang.String].""");
55+
Unable to replace bean: there is no bean with name 'beanToOverride' \
56+
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
5757
}
5858

5959
@Test
@@ -63,8 +63,8 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6363
assertThatIllegalStateException()
6464
.isThrownBy(context::refresh)
6565
.withMessage("""
66-
Unable to override bean: no beans of \
67-
type %s (as required by annotated field '%s.example')""".formatted(
66+
Unable to override bean: there are no beans of \
67+
type %s (as required by field '%s.example').""".formatted(
6868
String.class.getName(), FailureByTypeLookup.class.getSimpleName()));
6969
}
7070

@@ -77,9 +77,8 @@ void cannotOverrideBeanByTypeWithTooManyBeansOfThatType() {
7777
assertThatIllegalStateException()
7878
.isThrownBy(context::refresh)
7979
.withMessage("""
80-
Unable to select a bean to override: found 2 beans \
81-
of type %s (as required by annotated field '%s.example'): %s""".formatted(
82-
String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2")));
80+
Unable to select a bean to override: found 2 beans of type java.lang.String \
81+
(as required by field 'FailureByTypeLookup.example'): %s""", List.of("bean1", "bean2"));
8382
}
8483

8584
@Test

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

+9-10
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ void cannotOverrideBeanByNameWithNoSuchBeanName() {
4141
assertThatIllegalStateException()
4242
.isThrownBy(context::refresh)
4343
.withMessage("""
44-
Unable to override bean: there is no bean \
45-
to replace with name [beanToOverride] and type [java.lang.String].""");
44+
Unable to replace bean: there is no bean with name 'beanToOverride' \
45+
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
4646
}
4747

4848
@Test
@@ -53,8 +53,8 @@ void cannotOverrideBeanByNameWithBeanOfWrongType() {
5353
assertThatIllegalStateException()
5454
.isThrownBy(context::refresh)
5555
.withMessage("""
56-
Unable to override bean: there is no bean \
57-
to replace with name [beanToOverride] and type [java.lang.String].""");
56+
Unable to replace bean: there is no bean with name 'beanToOverride' \
57+
and type java.lang.String (as required by field 'FailureByNameLookup.example').""");
5858
}
5959

6060
@Test
@@ -64,9 +64,8 @@ void cannotOverrideBeanByTypeWithNoSuchBeanType() {
6464
assertThatIllegalStateException()
6565
.isThrownBy(context::refresh)
6666
.withMessage("""
67-
Unable to override bean: no beans of \
68-
type %s (as required by annotated field '%s.example')""".formatted(
69-
String.class.getName(), FailureByTypeLookup.class.getSimpleName()));
67+
Unable to override bean: there are no beans of \
68+
type java.lang.String (as required by field 'FailureByTypeLookup.example').""");
7069
}
7170

7271
@Test
@@ -78,9 +77,9 @@ void cannotOverrideBeanByTypeWithTooManyBeansOfThatType() {
7877
assertThatIllegalStateException()
7978
.isThrownBy(context::refresh)
8079
.withMessage("""
81-
Unable to select a bean to override: found 2 beans \
82-
of type %s (as required by annotated field '%s.example'): %s""".formatted(
83-
String.class.getName(), FailureByTypeLookup.class.getSimpleName(), List.of("bean1", "bean2")));
80+
Unable to select a bean to override: found 2 beans of type java.lang.String \
81+
(as required by field 'FailureByTypeLookup.example'): %s""",
82+
List.of("bean1", "bean2"));
8483
}
8584

8685

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

+8-10
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,9 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanName() {
4040
assertThatIllegalStateException()
4141
.isThrownBy(context::refresh)
4242
.withMessage("""
43-
Unable to override bean by wrapping: \
44-
there is no existing bean with name [beanToSpy] and type [%s].""",
45-
String.class.getName());
46-
}
43+
Unable to wrap bean: there is no bean with name 'beanToSpy' and \
44+
type java.lang.String (as required by field 'ByNameSingleLookup.example').""");
45+
}
4746

4847
@Test
4948
void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
@@ -52,9 +51,8 @@ void contextCustomizerCannotBeCreatedWithNoSuchBeanType() {
5251
assertThatIllegalStateException()
5352
.isThrownBy(context::refresh)
5453
.withMessage("""
55-
Unable to select a bean to override by wrapping: found 0 bean instances of \
56-
type %s (as required by annotated field '%s.example')""",
57-
String.class.getName(), ByTypeSingleLookup.class.getSimpleName());
54+
Unable to select a bean to wrap: there are no beans of type java.lang.String \
55+
(as required by field 'ByTypeSingleLookup.example').""");
5856
}
5957

6058
@Test
@@ -66,9 +64,9 @@ void contextCustomizerCannotBeCreatedWithTooManyBeansOfThatType() {
6664
assertThatIllegalStateException()
6765
.isThrownBy(context::refresh)
6866
.withMessage("""
69-
Unable to select a bean to override by wrapping: found 2 bean instances \
70-
of type %s (as required by annotated field '%s.example'): %s""",
71-
String.class.getName(), ByTypeSingleLookup.class.getSimpleName(), List.of("bean1", "bean2"));
67+
Unable to select a bean to wrap: found 2 beans of type java.lang.String \
68+
(as required by field 'ByTypeSingleLookup.example'): %s""",
69+
List.of("bean1", "bean2"));
7270
}
7371

7472

0 commit comments

Comments
 (0)