Skip to content

Commit a68d4ae

Browse files
committed
Register runtime hints for ActiveProfilesResolvers
This commit introduces automatic registration of runtime hints for custom ActiveProfilesResolver implementations configured via the `resolver` attribute in @activeprofiles. Closes gh-29022
1 parent 8d6d3f2 commit a68d4ae

File tree

6 files changed

+103
-7
lines changed

6 files changed

+103
-7
lines changed

spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@
2020
import java.util.List;
2121

2222
import org.springframework.aot.hint.RuntimeHints;
23+
import org.springframework.core.annotation.MergedAnnotations;
24+
import org.springframework.test.context.ActiveProfiles;
25+
import org.springframework.test.context.ActiveProfilesResolver;
2326
import org.springframework.test.context.ContextLoader;
2427
import org.springframework.test.context.MergedContextConfiguration;
28+
import org.springframework.test.context.TestContextAnnotationUtils;
2529
import org.springframework.test.context.aot.TestRuntimeHintsRegistrar;
2630
import org.springframework.test.context.web.WebMergedContextConfiguration;
2731

2832
import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS;
33+
import static org.springframework.core.annotation.MergedAnnotations.SearchStrategy.TYPE_HIERARCHY;
2934
import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX;
3035

3136
/**
@@ -46,6 +51,7 @@ public void registerHints(RuntimeHints runtimeHints, MergedContextConfiguration
4651
List<Class<?>> testClasses, ClassLoader classLoader) {
4752

4853
registerHintsForMergedContextConfiguration(runtimeHints, mergedConfig);
54+
testClasses.forEach(testClass -> registerHintsForActiveProfilesResolvers(runtimeHints, testClass));
4955
}
5056

5157
private void registerHintsForMergedContextConfiguration(
@@ -73,6 +79,17 @@ private void registerHintsForMergedContextConfiguration(
7379
}
7480
}
7581

82+
private void registerHintsForActiveProfilesResolvers(RuntimeHints runtimeHints, Class<?> testClass) {
83+
// @ActiveProfiles(resolver = ...)
84+
MergedAnnotations.search(TYPE_HIERARCHY)
85+
.withEnclosingClasses(TestContextAnnotationUtils::searchEnclosingClass)
86+
.from(testClass)
87+
.stream(ActiveProfiles.class)
88+
.map(mergedAnnotation -> mergedAnnotation.getClass("resolver"))
89+
.filter(type -> type != ActiveProfilesResolver.class)
90+
.forEach(resolverClass -> registerDeclaredConstructors(runtimeHints, resolverClass));
91+
}
92+
7693
private void registerDeclaredConstructors(RuntimeHints runtimeHints, Class<?> type) {
7794
runtimeHints.reflection().registerType(type, INVOKE_DECLARED_CONSTRUCTORS);
7895
}

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.context.ApplicationContext;
3636
import org.springframework.context.ApplicationContextInitializer;
3737
import org.springframework.context.ConfigurableApplicationContext;
38+
import org.springframework.core.env.Profiles;
3839
import org.springframework.javapoet.ClassName;
3940
import org.springframework.test.context.MergedContextConfiguration;
4041
import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterSharedConfigTests;
@@ -162,13 +163,15 @@ private static void assertRuntimeHints(RuntimeHints runtimeHints) {
162163
Stream.of(
163164
// @BootstrapWith
164165
org.springframework.test.context.aot.samples.basic.BasicSpringVintageTests.CustomXmlBootstrapper.class,
165-
// @ContextConfiguration(initializers=...)
166+
// @ContextConfiguration(initializers = ...)
166167
org.springframework.test.context.aot.samples.basic.BasicSpringTestNGTests.CustomInitializer.class,
167-
// @ContextConfiguration(loader=...)
168-
org.springframework.test.context.support.AnnotationConfigContextLoader.class
168+
// @ContextConfiguration(loader = ...)
169+
org.springframework.test.context.support.AnnotationConfigContextLoader.class,
170+
// @ActiveProfiles(resolver = ...)
171+
org.springframework.test.context.aot.samples.basic.SpanishActiveProfilesResolver.class
169172
).forEach(type -> assertReflectionRegistered(runtimeHints, type, INVOKE_DECLARED_CONSTRUCTORS));
170173

171-
// @ContextConfiguration(locations=...)
174+
// @ContextConfiguration(locations = ...)
172175
assertThat(resource().forResource("/org/springframework/test/context/aot/samples/xml/test-config.xml"))
173176
.accepts(runtimeHints);
174177

@@ -216,7 +219,10 @@ private void assertContextForBasicTests(ApplicationContext context) {
216219
assertThat(context.getEnvironment().getProperty("test.engine")).as("Environment").isNotNull();
217220

218221
MessageService messageService = context.getBean(MessageService.class);
219-
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!");
222+
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
223+
String expectedMessage = cac.getEnvironment().acceptsProfiles(Profiles.of("spanish")) ?
224+
"¡Hola, AOT!" : "Hello, AOT!";
225+
assertThat(messageService.generateMessage()).isEqualTo(expectedMessage);
220226
}
221227

222228
private void assertContextForBasicWebTests(WebApplicationContext wac) throws Exception {

spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicSpringJupiterTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.beans.factory.annotation.Autowired;
2424
import org.springframework.beans.factory.annotation.Value;
2525
import org.springframework.context.ApplicationContext;
26+
import org.springframework.test.context.ActiveProfiles;
2627
import org.springframework.test.context.TestExecutionListeners;
2728
import org.springframework.test.context.TestPropertySource;
2829
import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterTests.DummyExtension;
@@ -57,12 +58,13 @@ void test(@Autowired ApplicationContext context, @Autowired MessageService messa
5758

5859
@Nested
5960
@TestPropertySource(properties = "foo=bar")
61+
@ActiveProfiles(resolver = SpanishActiveProfilesResolver.class)
6062
public class NestedTests {
6163

6264
@org.junit.jupiter.api.Test
6365
void test(@Autowired ApplicationContext context, @Autowired MessageService messageService,
6466
@Value("${test.engine}") String testEngine, @Value("${foo}") String foo) {
65-
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!");
67+
assertThat(messageService.generateMessage()).isEqualTo("¡Hola, AOT!");
6668
assertThat(foo).isEqualTo("bar");
6769
assertThat(testEngine).isEqualTo("jupiter");
6870
assertThat(context.getEnvironment().getProperty("test.engine"))

spring-test/src/test/java/org/springframework/test/context/aot/samples/basic/BasicTestConfiguration.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import org.springframework.context.annotation.Bean;
2020
import org.springframework.context.annotation.Configuration;
21+
import org.springframework.context.annotation.Profile;
2122
import org.springframework.test.context.aot.samples.common.DefaultMessageService;
2223
import org.springframework.test.context.aot.samples.common.MessageService;
24+
import org.springframework.test.context.aot.samples.common.SpanishMessageService;
2325

2426
/**
2527
* @author Sam Brannen
@@ -29,8 +31,15 @@
2931
class BasicTestConfiguration {
3032

3133
@Bean
32-
MessageService messageService() {
34+
@Profile("default")
35+
MessageService defaultMessageService() {
3336
return new DefaultMessageService();
3437
}
3538

39+
@Bean
40+
@Profile("spanish")
41+
MessageService spanishMessageService() {
42+
return new SpanishMessageService();
43+
}
44+
3645
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.basic;
18+
19+
import org.springframework.test.context.ActiveProfilesResolver;
20+
21+
/**
22+
* @author Sam Brannen
23+
* @since 6.0
24+
*/
25+
public class SpanishActiveProfilesResolver implements ActiveProfilesResolver {
26+
27+
@Override
28+
public String[] resolve(Class<?> testClass) {
29+
return new String[] { "spanish" };
30+
}
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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.common;
18+
19+
/**
20+
* @author Sam Brannen
21+
* @since 6.0
22+
*/
23+
public class SpanishMessageService implements MessageService {
24+
25+
@Override
26+
public String generateMessage() {
27+
return "¡Hola, AOT!";
28+
}
29+
30+
}

0 commit comments

Comments
 (0)