Skip to content

Commit b0d6570

Browse files
committed
Test XML, Web, & @TestPropertySource AOT support
See gh-28204, gh-28205
1 parent 84c3779 commit b0d6570

File tree

10 files changed

+540
-30
lines changed

10 files changed

+540
-30
lines changed

spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorTests.java

Lines changed: 88 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.ArrayList;
2020
import java.util.List;
2121
import java.util.Set;
22-
import java.util.function.Consumer;
2322
import java.util.stream.Stream;
2423

2524
import org.junit.jupiter.api.Test;
@@ -29,6 +28,7 @@
2928
import org.springframework.aot.generate.InMemoryGeneratedFiles;
3029
import org.springframework.aot.test.generator.compile.CompileWithTargetClassAccess;
3130
import org.springframework.aot.test.generator.compile.TestCompiler;
31+
import org.springframework.context.ApplicationContext;
3232
import org.springframework.context.ApplicationContextInitializer;
3333
import org.springframework.context.support.GenericApplicationContext;
3434
import org.springframework.javapoet.ClassName;
@@ -38,8 +38,21 @@
3838
import org.springframework.test.context.aot.samples.basic.BasicSpringTestNGTests;
3939
import org.springframework.test.context.aot.samples.basic.BasicSpringVintageTests;
4040
import org.springframework.test.context.aot.samples.common.MessageService;
41+
import org.springframework.test.context.aot.samples.web.WebSpringJupiterTests;
42+
import org.springframework.test.context.aot.samples.web.WebSpringTestNGTests;
43+
import org.springframework.test.context.aot.samples.web.WebSpringVintageTests;
44+
import org.springframework.test.context.aot.samples.xml.XmlSpringJupiterTests;
45+
import org.springframework.test.context.aot.samples.xml.XmlSpringTestNGTests;
46+
import org.springframework.test.context.aot.samples.xml.XmlSpringVintageTests;
47+
import org.springframework.test.web.servlet.MockMvc;
48+
import org.springframework.util.function.ThrowingConsumer;
49+
import org.springframework.web.context.WebApplicationContext;
4150

4251
import static org.assertj.core.api.Assertions.assertThat;
52+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
53+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
54+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
55+
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
4356

4457
/**
4558
* Tests for {@link TestContextAotGenerator}.
@@ -76,50 +89,95 @@ void generate() {
7689
}
7790

7891
@Test
79-
// We cannot parameterize with the test classes, since @CompileWithTargetClassAccess
80-
// cannot support @ParameterizedTest methods.
81-
void generateApplicationContextInitializer() {
82-
InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
83-
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
92+
void processAheadOfTimeWithBasicTests() {
93+
// We cannot parameterize with the test classes, since @CompileWithTargetClassAccess
94+
// cannot support @ParameterizedTest methods.
8495
Set<Class<?>> testClasses = Set.of(
85-
BasicSpringTestNGTests.class,
86-
BasicSpringVintageTests.class,
96+
BasicSpringJupiterSharedConfigTests.class,
8797
BasicSpringJupiterTests.class,
88-
BasicSpringJupiterSharedConfigTests.class);
89-
List<ClassName> classNames = new ArrayList<>();
90-
testClasses.forEach(testClass -> {
91-
DefaultGenerationContext generationContext = generator.createGenerationContext(testClass);
92-
MergedContextConfiguration mergedConfig = generator.buildMergedContextConfiguration(testClass);
93-
ClassName className = generator.processAheadOfTime(mergedConfig, generationContext);
94-
assertThat(className).isNotNull();
95-
classNames.add(className);
96-
generationContext.writeGeneratedContent();
98+
BasicSpringJupiterTests.NestedTests.class,
99+
BasicSpringTestNGTests.class,
100+
BasicSpringVintageTests.class);
101+
102+
processAheadOfTime(testClasses, context -> {
103+
assertThat(context.getEnvironment().getProperty("test.engine"))
104+
.as("Environment").isNotNull();
105+
106+
MessageService messageService = context.getBean(MessageService.class);
107+
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!");
97108
});
109+
}
110+
111+
@Test
112+
void processAheadOfTimeWithXmlTests() {
113+
// We cannot parameterize with the test classes, since @CompileWithTargetClassAccess
114+
// cannot support @ParameterizedTest methods.
115+
Set<Class<?>> testClasses = Set.of(
116+
XmlSpringJupiterTests.class,
117+
XmlSpringTestNGTests.class,
118+
XmlSpringVintageTests.class);
119+
120+
processAheadOfTime(testClasses, context -> {
121+
assertThat(context.getEnvironment().getProperty("test.engine"))
122+
.as("Environment").isNotNull();
98123

99-
compile(generatedFiles, classNames, context -> {
100124
MessageService messageService = context.getBean(MessageService.class);
101125
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!");
102-
// TODO Support @TestPropertySource in AOT testing mode.
103-
// assertThat(context.getEnvironment().getProperty("test.engine"))
104-
// .as("@TestPropertySource").isNotNull();
105126
});
106127
}
107128

129+
@Test
130+
void processAheadOfTimeWithWebTests() {
131+
// We cannot parameterize with the test classes, since @CompileWithTargetClassAccess
132+
// cannot support @ParameterizedTest methods.
133+
Set<Class<?>> testClasses = Set.of(
134+
WebSpringJupiterTests.class,
135+
WebSpringTestNGTests.class,
136+
WebSpringVintageTests.class);
108137

109-
@SuppressWarnings("unchecked")
110-
private void compile(InMemoryGeneratedFiles generatedFiles, List<ClassName> classNames,
111-
Consumer<GenericApplicationContext> result) {
138+
processAheadOfTime(testClasses, context -> {
139+
assertThat(context.getEnvironment().getProperty("test.engine"))
140+
.as("Environment").isNotNull();
141+
142+
MockMvc mockMvc = webAppContextSetup((WebApplicationContext) context).build();
143+
mockMvc.perform(get("/hello"))
144+
.andExpectAll(status().isOk(), content().string("Hello, AOT!"));
145+
});
146+
}
112147

148+
149+
@SuppressWarnings("unchecked")
150+
private void processAheadOfTime(Set<Class<?>> testClasses, ThrowingConsumer<ApplicationContext> result) {
151+
InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
152+
TestContextAotGenerator generator = new TestContextAotGenerator(generatedFiles);
153+
List<Mapping> mappings = processAheadOfTime(generator, testClasses);
113154
TestCompiler.forSystem().withFiles(generatedFiles).compile(compiled -> {
114-
classNames.forEach(className -> {
115-
GenericApplicationContext gac = new GenericApplicationContext();
155+
mappings.forEach(mapping -> {
156+
MergedContextConfiguration mergedConfig = mapping.mergedConfig();
116157
ApplicationContextInitializer<GenericApplicationContext> contextInitializer =
117-
compiled.getInstance(ApplicationContextInitializer.class, className.reflectionName());
118-
contextInitializer.initialize(gac);
119-
gac.refresh();
120-
result.accept(gac);
158+
compiled.getInstance(ApplicationContextInitializer.class, mapping.className().reflectionName());
159+
AotRuntimeContextLoader aotRuntimeContextLoader = new AotRuntimeContextLoader();
160+
GenericApplicationContext context = aotRuntimeContextLoader.loadContext(mergedConfig, contextInitializer);
161+
result.accept(context);
121162
});
122163
});
123164
}
124165

166+
private List<Mapping> processAheadOfTime(TestContextAotGenerator generator, Set<Class<?>> testClasses) {
167+
List<Mapping> mappings = new ArrayList<>();
168+
testClasses.forEach(testClass -> {
169+
DefaultGenerationContext generationContext = generator.createGenerationContext(testClass);
170+
MergedContextConfiguration mergedConfig = generator.buildMergedContextConfiguration(testClass);
171+
ClassName className = generator.processAheadOfTime(mergedConfig, generationContext);
172+
assertThat(className).isNotNull();
173+
mappings.add(new Mapping(mergedConfig, className));
174+
generationContext.writeGeneratedContent();
175+
});
176+
return mappings;
177+
}
178+
179+
180+
record Mapping(MergedContextConfiguration mergedConfig, ClassName className) {
181+
}
182+
125183
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2002-2022 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.aot.samples.web;
18+
19+
import org.springframework.web.bind.annotation.GetMapping;
20+
import org.springframework.web.bind.annotation.RestController;
21+
22+
/**
23+
* @author Sam Brannen
24+
* @since 6.0
25+
*/
26+
@RestController
27+
class MessageController {
28+
29+
@GetMapping("/hello")
30+
String hello() {
31+
return "Hello, AOT!";
32+
}
33+
34+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2002-2022 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.aot.samples.web;
18+
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.beans.factory.annotation.Value;
21+
import org.springframework.test.context.TestPropertySource;
22+
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
23+
import org.springframework.test.web.servlet.MockMvc;
24+
import org.springframework.web.context.WebApplicationContext;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
28+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
29+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
30+
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
31+
32+
/**
33+
* @author Sam Brannen
34+
* @since 6.0
35+
*/
36+
@SpringJUnitWebConfig(WebTestConfiguration.class)
37+
@TestPropertySource(properties = "test.engine = jupiter")
38+
public class WebSpringJupiterTests {
39+
40+
MockMvc mockMvc;
41+
42+
@Autowired
43+
WebApplicationContext wac;
44+
45+
46+
@org.junit.jupiter.api.BeforeEach
47+
void setUpMockMvc() {
48+
this.mockMvc = webAppContextSetup(this.wac).build();
49+
}
50+
51+
@org.junit.jupiter.api.Test
52+
void test(@Value("${test.engine}") String testEngine) throws Exception {
53+
assertThat(testEngine)
54+
.as("@Value").isEqualTo("jupiter");
55+
assertThat(wac.getEnvironment().getProperty("test.engine"))
56+
.as("Environment").isEqualTo("jupiter");
57+
58+
mockMvc.perform(get("/hello"))
59+
.andExpectAll(status().isOk(), content().string("Hello, AOT!"));
60+
}
61+
62+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2002-2022 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.aot.samples.web;
18+
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.beans.factory.annotation.Value;
21+
import org.springframework.test.context.ContextConfiguration;
22+
import org.springframework.test.context.TestPropertySource;
23+
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
24+
import org.springframework.test.context.web.WebAppConfiguration;
25+
import org.springframework.test.web.servlet.MockMvc;
26+
import org.springframework.web.context.WebApplicationContext;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
30+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
31+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
32+
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
33+
34+
/**
35+
* @author Sam Brannen
36+
* @since 6.0
37+
*/
38+
@ContextConfiguration(classes = WebTestConfiguration.class)
39+
@WebAppConfiguration
40+
@TestPropertySource(properties = "test.engine = testng")
41+
public class WebSpringTestNGTests extends AbstractTestNGSpringContextTests {
42+
43+
MockMvc mockMvc;
44+
45+
@Autowired
46+
WebApplicationContext wac;
47+
48+
@Value("${test.engine}")
49+
String testEngine;
50+
51+
52+
@org.testng.annotations.BeforeMethod
53+
public void setUpMockMvc() {
54+
this.mockMvc = webAppContextSetup(this.wac).build();
55+
}
56+
57+
@org.testng.annotations.Test
58+
public void test() throws Exception {
59+
assertThat(testEngine)
60+
.as("@Value").isEqualTo("testng");
61+
assertThat(wac.getEnvironment().getProperty("test.engine"))
62+
.as("Environment").isEqualTo("testng");
63+
64+
mockMvc.perform(get("/hello"))
65+
.andExpectAll(status().isOk(), content().string("Hello, AOT!"));
66+
}
67+
68+
}

0 commit comments

Comments
 (0)