Skip to content

Commit 6b79d28

Browse files
committed
Merge branch '2.5.x' into main
Closes gh-28724
2 parents e17461e + 64270ec commit 6b79d28

File tree

6 files changed

+197
-22
lines changed

6 files changed

+197
-22
lines changed

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootContextLoader.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,6 @@ public ApplicationContext loadContext(MergedContextConfiguration config) throws
9191
application.setMainApplicationClass(config.getTestClass());
9292
application.addPrimarySources(Arrays.asList(configClasses));
9393
application.getSources().addAll(Arrays.asList(configLocations));
94-
ConfigurableEnvironment environment = getEnvironment();
95-
if (!ObjectUtils.isEmpty(config.getActiveProfiles())) {
96-
setActiveProfiles(environment, config.getActiveProfiles());
97-
}
98-
ResourceLoader resourceLoader = (application.getResourceLoader() != null) ? application.getResourceLoader()
99-
: new DefaultResourceLoader(null);
100-
TestPropertySourceUtils.addPropertiesFilesToEnvironment(environment, resourceLoader,
101-
config.getPropertySourceLocations());
102-
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, getInlinedProperties(config));
103-
application.setEnvironment(environment);
10494
List<ApplicationContextInitializer<?>> initializers = getInitializers(config, application);
10595
if (config instanceof WebMergedContextConfiguration) {
10696
application.setWebApplicationType(WebApplicationType.SERVLET);
@@ -119,10 +109,40 @@ else if (config instanceof ReactiveWebMergedContextConfiguration) {
119109
application.setWebApplicationType(WebApplicationType.NONE);
120110
}
121111
application.setInitializers(initializers);
112+
ConfigurableEnvironment environment = getEnvironment(application, config.getActiveProfiles());
113+
ResourceLoader resourceLoader = (application.getResourceLoader() != null) ? application.getResourceLoader()
114+
: new DefaultResourceLoader(null);
115+
TestPropertySourceUtils.addPropertiesFilesToEnvironment(environment, resourceLoader,
116+
config.getPropertySourceLocations());
117+
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, getInlinedProperties(config));
118+
application.setEnvironment(environment);
122119
String[] args = SpringBootTestArgs.get(config.getContextCustomizers());
123120
return application.run(args);
124121
}
125122

123+
private ConfigurableEnvironment getEnvironment(SpringApplication application, String[] activeProfiles) {
124+
ConfigurableEnvironment environment = getEnvironment();
125+
boolean applicationEnvironment = false;
126+
if (environment.getClass() == StandardEnvironment.class) {
127+
environment = application.convertEnvironment(environment);
128+
applicationEnvironment = true;
129+
}
130+
setActiveProfiles(environment, activeProfiles, applicationEnvironment);
131+
return environment;
132+
}
133+
134+
private void setActiveProfiles(ConfigurableEnvironment environment, String[] profiles,
135+
boolean applicationEnvironment) {
136+
if (!applicationEnvironment) {
137+
environment.setActiveProfiles(profiles);
138+
}
139+
String[] pairs = new String[profiles.length];
140+
for (int i = 0; i < profiles.length; i++) {
141+
pairs[i] = "spring.profiles.active[" + i + "]=" + profiles[i];
142+
}
143+
TestPropertyValues.of(pairs).applyTo(environment);
144+
}
145+
126146
/**
127147
* Builds new {@link org.springframework.boot.SpringApplication} instance. You can
128148
* override this method to add custom behavior
@@ -141,16 +161,6 @@ protected ConfigurableEnvironment getEnvironment() {
141161
return new StandardEnvironment();
142162
}
143163

144-
private void setActiveProfiles(ConfigurableEnvironment environment, String[] profiles) {
145-
environment.setActiveProfiles(profiles);
146-
// Also add as properties to override any application.properties
147-
String[] pairs = new String[profiles.length];
148-
for (int i = 0; i < profiles.length; i++) {
149-
pairs[i] = "spring.profiles.active[" + i + "]=" + profiles[i];
150-
}
151-
TestPropertyValues.of(pairs).applyTo(environment);
152-
}
153-
154164
protected String[] getInlinedProperties(MergedContextConfiguration config) {
155165
ArrayList<String> properties = new ArrayList<>();
156166
// JMX bean names will clash if the same bean is used in multiple contexts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2012-2021 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.boot.test.context;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.context.annotation.Configuration;
23+
import org.springframework.core.env.ConfigurableEnvironment;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.mock.env.MockEnvironment;
26+
import org.springframework.test.context.ActiveProfiles;
27+
import org.springframework.test.context.ContextConfiguration;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
31+
/**
32+
* Integration tests for {@link SpringBootTest @SpringBootTest} with a custom
33+
* {@link Environment}.
34+
*
35+
* @author Madhura Bhave
36+
*/
37+
@SpringBootTest
38+
@ActiveProfiles({ "test1", "test2" })
39+
@ContextConfiguration(loader = SpringBootTestWithCustomEnvironmentTests.Loader.class)
40+
class SpringBootTestWithCustomEnvironmentTests {
41+
42+
@Autowired
43+
private Environment environment;
44+
45+
@Test
46+
void getActiveProfiles() {
47+
assertThat(this.environment).isInstanceOf(MockEnvironment.class);
48+
assertThat(this.environment.getActiveProfiles()).containsOnly("test1", "test2");
49+
}
50+
51+
@Configuration
52+
static class Config {
53+
54+
}
55+
56+
static class Loader extends SpringBootContextLoader {
57+
58+
@Override
59+
protected ConfigurableEnvironment getEnvironment() {
60+
return new MockEnvironment();
61+
}
62+
63+
}
64+
65+
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,24 @@ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners
341341
"Environment prefix cannot be set via properties.");
342342
bindToSpringApplication(environment);
343343
if (!this.isCustomEnvironment) {
344-
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
345-
deduceEnvironmentClass());
344+
environment = convertEnvironment(environment);
346345
}
347346
ConfigurationPropertySources.attach(environment);
348347
return environment;
349348
}
350349

350+
/**
351+
* Convert the given {@link ConfigurableEnvironment environment} to an application
352+
* environment that doesn't attempt to resolve profile properties directly.
353+
* @param environment the environment to convert
354+
* @return the converted environment
355+
* @since 2.5.7
356+
*/
357+
public StandardEnvironment convertEnvironment(ConfigurableEnvironment environment) {
358+
return new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
359+
deduceEnvironmentClass());
360+
}
361+
351362
private Class<? extends StandardEnvironment> deduceEnvironmentClass() {
352363
switch (this.webApplicationType) {
353364
case SERVLET:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2012-2021 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 smoketest.profile;
18+
19+
import org.springframework.boot.SpringApplication;
20+
import org.springframework.boot.env.EnvironmentPostProcessor;
21+
import org.springframework.core.Ordered;
22+
import org.springframework.core.annotation.Order;
23+
import org.springframework.core.env.ConfigurableEnvironment;
24+
25+
/**
26+
* {@link EnvironmentPostProcessor} that adds an active profile.
27+
*
28+
* @author Madhura Bhave
29+
*/
30+
@Order(Ordered.HIGHEST_PRECEDENCE)
31+
class ActiveProfilesEnvironmentPostProcessor implements EnvironmentPostProcessor {
32+
33+
@Override
34+
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
35+
if (environment.getProperty("enableEnvironmentPostProcessor") != null) {
36+
environment.addActiveProfile("dev");
37+
}
38+
}
39+
40+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.boot.env.EnvironmentPostProcessor=\
2+
smoketest.profile.ActiveProfilesEnvironmentPostProcessor
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2012-2021 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 smoketest.profile;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.boot.env.EnvironmentPostProcessor;
23+
import org.springframework.boot.test.context.SpringBootTest;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.test.context.ActiveProfiles;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
/**
30+
* Tests that profiles are activited in the correct order from an
31+
* {@link EnvironmentPostProcessor}.
32+
*
33+
* @author Madhura Bhave
34+
*/
35+
@SpringBootTest(properties = "enableEnvironmentPostProcessor=true") // gh-28530
36+
@ActiveProfiles("hello")
37+
class ActiveProfilesTests {
38+
39+
@Autowired
40+
private Environment environment;
41+
42+
@Test
43+
void activeProfileShouldTakePrecedenceOverProgrammaticallySetProfile() {
44+
assertThat(this.environment.getActiveProfiles()).containsExactly("dev", "hello");
45+
}
46+
47+
}

0 commit comments

Comments
 (0)