Skip to content

Commit 31f8e12

Browse files
committed
Separate failure and success scenario tests for @⁠TestBean
This commit also ensures that @⁠Bean methods are declared within @⁠Configuration classes instead of within test classes. See gh-29122
1 parent 1f537b9 commit 31f8e12

File tree

2 files changed

+235
-160
lines changed

2 files changed

+235
-160
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.bean.override.convention;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.platform.engine.TestExecutionResult;
21+
import org.junit.platform.testkit.engine.EngineExecutionResults;
22+
import org.junit.platform.testkit.engine.EngineTestKit;
23+
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.test.context.aot.DisabledInAotMode;
27+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.assertj.core.api.Assertions.fail;
31+
import static org.assertj.core.api.InstanceOfAssertFactories.THROWABLE;
32+
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
33+
34+
/**
35+
* {@link TestBean @TestBean} integration tests for failure scenarios.
36+
*
37+
* @since 6.2
38+
* @see TestBeanIntegrationTests
39+
*/
40+
public class FailingTestBeanIntegrationTests {
41+
42+
@Test
43+
void testBeanFailingNoFieldNameBean() {
44+
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
45+
.selectors(selectClass(NoOriginalBeanTestCase.class))//
46+
.execute();
47+
48+
assertThat(results.allEvents().failed().stream()).hasSize(1).first()
49+
.satisfies(e -> assertThat(e.getRequiredPayload(TestExecutionResult.class)
50+
.getThrowable()).get(THROWABLE)
51+
.cause()
52+
.isInstanceOf(IllegalStateException.class)
53+
.hasMessage("Unable to override bean 'noOriginalBean'; " +
54+
"there is no bean definition to replace with that name of type java.lang.String"));
55+
}
56+
57+
@Test
58+
void testBeanFailingNoExplicitNameBean() {
59+
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
60+
.selectors(selectClass(BeanDefinitionToOverrideNotPresentTestCase.class))//
61+
.execute();
62+
63+
assertThat(results.allEvents().failed().stream()).hasSize(1).first()
64+
.satisfies(e -> assertThat(e.getRequiredPayload(TestExecutionResult.class)
65+
.getThrowable()).get(THROWABLE)
66+
.cause()
67+
.isInstanceOf(IllegalStateException.class)
68+
.hasMessage("Unable to override bean 'notPresent'; " +
69+
"there is no bean definition to replace with that name of type java.lang.String"));
70+
}
71+
72+
@Test
73+
void testBeanFailingNoImplicitMethod() {
74+
Class<?> testClass = ExplicitTestOverrideMethodNotPresentTestCase.class;
75+
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
76+
.selectors(selectClass(testClass))//
77+
.execute();
78+
79+
assertThat(results.allEvents().failed().stream()).hasSize(1).first()
80+
.satisfies(e -> assertThat(e.getRequiredPayload(TestExecutionResult.class)
81+
.getThrowable()).get(THROWABLE)
82+
.rootCause().isInstanceOf(IllegalStateException.class)
83+
.hasMessage("Failed to find a static test bean factory method in %s " +
84+
"with return type java.lang.String whose name matches one of the " +
85+
"supported candidates [notPresent]", testClass.getName()));
86+
}
87+
88+
@Test
89+
void testBeanFailingNoExplicitMethod() {
90+
Class<?> testClass = ImplicitTestOverrideMethodNotPresentTestCase.class;
91+
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
92+
.selectors(selectClass(testClass))//
93+
.execute();
94+
95+
assertThat(results.allEvents().failed().stream()).hasSize(1).first()
96+
.satisfies(e -> assertThat(e.getRequiredPayload(TestExecutionResult.class)
97+
.getThrowable()).get(THROWABLE)
98+
.rootCause().isInstanceOf(IllegalStateException.class)
99+
.hasMessage("Failed to find a static test bean factory method in %s " +
100+
"with return type java.lang.String whose name matches one of the " +
101+
"supported candidates [fieldTestOverride]", testClass.getName()));
102+
}
103+
104+
@Test
105+
void testBeanFailingBeanOfWrongType() {
106+
EngineExecutionResults results = EngineTestKit.engine("junit-jupiter")//
107+
.selectors(selectClass(BeanTypeMismatchTestCase.class))//
108+
.execute();
109+
110+
assertThat(results.allEvents().failed().stream()).hasSize(1).first()
111+
.satisfies(e -> assertThat(e.getRequiredPayload(TestExecutionResult.class)
112+
.getThrowable()).get(THROWABLE)
113+
.rootCause().isInstanceOf(IllegalStateException.class)
114+
.hasMessage("Unable to override bean 'notString'; there is no bean definition to replace with " +
115+
"that name of type java.lang.String"));
116+
}
117+
118+
@Configuration
119+
static class Config {
120+
121+
@Bean("field")
122+
String bean1() {
123+
return "prod";
124+
}
125+
126+
@Bean("nestedField")
127+
String bean2() {
128+
return "nestedProd";
129+
}
130+
131+
@Bean("methodRenamed1")
132+
String bean3() {
133+
return "Prod";
134+
}
135+
136+
@Bean("methodRenamed2")
137+
String bean4() {
138+
return "NestedProd";
139+
}
140+
}
141+
142+
@SpringJUnitConfig
143+
@DisabledInAotMode
144+
static class NoOriginalBeanTestCase {
145+
146+
@TestBean(name = "noOriginalBean")
147+
String noOriginalBean;
148+
149+
@Test
150+
void ignored() {
151+
fail("should fail earlier");
152+
}
153+
154+
static String noOriginalBeanTestOverride() {
155+
return "should be ignored";
156+
}
157+
158+
}
159+
160+
@SpringJUnitConfig
161+
@DisabledInAotMode
162+
static class BeanDefinitionToOverrideNotPresentTestCase {
163+
164+
@TestBean(name = "notPresent")
165+
String field;
166+
167+
@Test
168+
void ignored() {
169+
fail("should fail earlier");
170+
}
171+
172+
static String notPresentTestOverride() {
173+
return "should be ignored";
174+
}
175+
}
176+
177+
@SpringJUnitConfig
178+
@DisabledInAotMode
179+
static class ExplicitTestOverrideMethodNotPresentTestCase {
180+
181+
@TestBean(methodName = "notPresent")
182+
String field;
183+
184+
@Test
185+
void ignored() {
186+
fail("should fail earlier");
187+
}
188+
}
189+
190+
@SpringJUnitConfig
191+
@DisabledInAotMode
192+
static class ImplicitTestOverrideMethodNotPresentTestCase {
193+
194+
@TestBean //expects fieldTestOverride method
195+
String field;
196+
197+
@Test
198+
void ignored() {
199+
fail("should fail earlier");
200+
}
201+
}
202+
203+
@SpringJUnitConfig
204+
@DisabledInAotMode
205+
static class BeanTypeMismatchTestCase {
206+
207+
@TestBean(name = "notString")
208+
String field;
209+
210+
@Test
211+
void ignored() {
212+
fail("should fail earlier");
213+
}
214+
215+
static String fieldTestOverride() {
216+
return "should be ignored";
217+
}
218+
219+
@Configuration
220+
static class Config {
221+
222+
@Bean("notString")
223+
StringBuilder bean1() {
224+
return new StringBuilder("not a String");
225+
}
226+
}
227+
}
228+
229+
}

0 commit comments

Comments
 (0)