1469 changed the semantic of @ActiveProfile in order to replace the list of active profiles. The previous behavior added the profiles specified in the annotation to the list of already active profiles.

I find #1469 relevant, but we lost the way to enable an additional profile.

I'd like to run a few tests with a slightly different profile (that's why I need to append a profile to the list of active ones to override a few values), but at the same time, I already launch the tests with a spring profile owning the environment dependent properties. Let's take an example: for one test, I want to set the timeout to 1 sec instead of 10mn (here is my additional profile), but I still want my application connect to the right URL (which is decided on the command like with the -Dspring.profiles.active={int,qa} switch).

NB: I'm not sure this is a pure spring-boot issue as @ActiveProfiles is part of spring-test; but as #1469 as treated here, I'm posting here too.

Comment From: wilkinsona

You can use spring.profiles.include to add additional profiles. Please see the documentation for further details. In a test, you could use the properties attribute of @SpringBootTest to set it.

Comment From: iksnalybok

I'm indeed running a test. I need a specific configuration just for on test, so I don't want to supply a spring.profiles.include flag on the command line.

Thanks for the suggestion (@SpringBootTest(properties=...)), but it does not work.

My additional profile file application-testSpringProfile.properties defines one property foo = bar.

Specifying a non-magic property works well (no profile here):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {GeneralConfiguration.class},
        properties = "foo=bar"
)
public class IT_SpringProfiles {

    @Value("${foo}")
    String foo;

    @Test public void dummy () {
        System.out.println("foo = "+foo);  // «foo = bar» is printed
    }
}

Specifying the spring.profiles.include property fails:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {GeneralConfiguration.class},
        properties = "spring.profiles.include=testSpringProfile"
)
public class IT_SpringProfiles {

    @Value("${foo}")  // error: Could not resolve placeholder 'foo' in string value "${foo}"
    String foo;

    @Test public void dummy () {
        System.out.println("foo = "+foo);
    }
}

Comment From: wilkinsona

Reopening to investigate why it doesn't work with @SpringBootTest

Comment From: wilkinsona

Well, to my surprise, I have learned that spring.profiles.include is only supported when used in a configuration file. That seems unnecessarily limited. Another option is to use SpringApplication.setAdditionalProfiles() but that doesn't help in a test without jumping through lots of hoops with custom bootstrappers and or context loaders.

Comment From: wilkinsona

The additive logic was introduced in #308 where spring.profiles.active and a profile name prefixed with a + was used to indicate that it should be additive. Looking at the original code, it worked with spring.profiles.active coming from any source. This was changed to spring.profiles.include in https://github.com/spring-projects/spring-boot/commit/a79ff19b00a3b975ba8506624a4e9abd56c2b92a at which point the support for including profiles from any property source appears to have been lost.

Comment From: philwebb

In a dark corner of my mind I seem to remember that may have been intentional but I can't remember why.

Comment From: iksnalybok

Like @org.springframework.test.context.ActiveProfiles maps to spring.profiles.active, it that reasonable to consider creating a similar annotation that would map to spring.profiles.include?

Comment From: wilkinsona

I think this will allow additional profiles to be activated:

diff --git a/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java
index 85c6bb7b9..46a3b74f3 100644
--- a/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java
+++ b/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -393,8 +394,11 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
                        }
                        // Any pre-existing active profiles set via property sources (e.g. System
                        // properties) take precedence over those added in config files.
-                       Set<Profile> activeProfiles = bindSpringProfiles(
-                                       this.environment.getPropertySources()).getActiveProfiles();
+                       SpringProfiles springProfiles = bindSpringProfiles(
+                                       this.environment.getPropertySources());
+                       Set<Profile> activeProfiles = new HashSet<Profile>(
+                                       springProfiles.getActiveProfiles());
+                       activeProfiles.addAll(springProfiles.getIncludeProfiles());
                        maybeActivateProfiles(activeProfiles);
                        return activeProfiles;
                }

Comment From: PeterWippermann

@wilkinsona Thanks for the analysis of the problem and its history. Why did you finally close the issue and did not add that valuable feature?

Comment From: wilkinsona

@PeterWippermann Why do you believe that the change wasn't made? This issue was closed by commit https://github.com/spring-projects/spring-boot/commit/393cfe505e20496dc69b54aa94ba944dcdb75f0f which allowed spring.profiles.include to be used anywhere, including in the properties configured via @SpringBootTest. It was then refined in https://github.com/spring-projects/spring-boot/commit/7dd8e8c4b8e9521aac55caef0cf94a14cea5c38e to fix a bug. In short, it should work fully from 1.5.2 onwards.

Comment From: PeterWippermann

Hi @wilkinsona, I must have been blind! Thanks for pointing me at this and sorry for bothering you.

Too bad that this is only available from 1.5 on. The 1.4.7 documentation is still misleading in regards of spring.profiles.include. There's no chance to fix it, is there? I assume all PRs will have to be merged against 1.5.x, right?

Comment From: wilkinsona

Correct. 1.4.x is now dormant and all users if 1.x are recommended to upgrade to 1.5.x which will be maintained long-term.

Comment From: szauner

Though this is closed I would like to share something that I just ran into. In my Spring Boot 2.0.4 Application I use the property spring.profiles.active in application.properties to define the active profile for development-convience. I use a command line instruction to overwrite this when needed. But when I try to add another provile for my tests using the way proposed here, the profiles defined in application.properties get discarded. Is that intentional behaviour or something that should be fixed?

Comment From: wilkinsona

@szauner Using spring.profiles.include in your test should add to the profiles activated by spring.profiles.active. If you have a situation where that's not the case, please open a new issue with a small sample that reproduces the problem.

Comment From: eppdot

@wilkinsona Thanks for the workaround, but I think it would be really beneficial to have a flag on @ActiveProfiles or an additional annotation like @AddActiveProfiles. Because now the property can only be set once right? And the last annotation takes it all. Thus, it could be really difficult to debug. Our use-case is the following:

We have a tag like @IntegrationTest which marks our integration test and results on loading a different @TestConfiguration with mocked/non-mocked beans. Additionally, we run these tests locally against a local database. On the other hand we run the test on jenkins against our CI infrastructure. There are a few solutions how to do that. First, run mvn test -Dspring.profiles.active=jenkins, Second SPRING_PROFILES_ACTIVE=jenkins, third have a custom ActiveProfileResolver that checks for an ENV variable JENKINS or user=jenkins and then activates an additional profile.

But I think all solutions have the same problems as being very limited, if we need multiple active profiles dynamically.

Comment From: vprudnikov

I need for adding additional profiles for testing when I can define my own annotation and specify that one or more profiles will be dynamically included. It's really strange that Spring doesn't support this. I spent hours and did not find a solution.

Comment From: nbrugger-tgm

Running this test with command line flag -Dspring.profiles.active=dev-env,dev,ad-search,ad-search-test,ad-search-postgres does NOT include the temp-db active profile.

@SpringBootTest(properties = {"spring.profiles.include=temp-db"})
//@ActiveProfiles(value = "temp-db", inheritProfiles = true)
public abstract class AdSearchDaoJunit5AbstractIT {

Output

[ INFO] [2023.11.08 15:43:03]  The following 5 profiles are active: "dev-env", "dev", "ad-search", "ad-search-test", "ad-search-postgres"