Affects: spring-test 5.3.3
Back with 5.2.1.RELEASE I could annotate a test class with:
@ActiveProfiles("${testprofiles.active:test}")
when supplying -Dtestprofiles.active=integrationtest
the context would load the resolved integrationtest
Profile:
org.springframework.core.env.StandardEnvironment - Activating profiles [integrationtest] com.iteratec.MyTest: The following profiles are active: integrationtest
After upgrading to 5.3.3 this doesn't seem to work anymore:
org.springframework.core.env.StandardEnvironment - Activating profiles [${testprofiles.active:test}] com.iteratec.MyTest: The following profiles are active: ${testprofiles.active:test}
and thus a fallback to no matching profile at all / base-properties happens.
Is this expected behavior or a bug?
I worked around this by using a custom ActiveProfilesResolver:
@ActiveProfiles(value = "test", resolver = SystemPropertyActiveProfilesResolver.class)
public class SystemPropertyActiveProfilesResolver implements ActiveProfilesResolver {
private final DefaultActiveProfilesResolver defaultActiveProfilesResolver = new DefaultActiveProfilesResolver();
@Override
public String[] resolve(Class<?> testClass) {
Assert.notNull(testClass, "Class must not be null");
if (System.getProperties().containsKey("spring.profiles.active")) {
final String profiles = System.getProperty("testprofiles.active");
return profiles.split("\\s*,\\s*");
} else {
return defaultActiveProfilesResolver.resolve(testClass);
}
}
}
Comment From: sbrannen
I was unable to reproduce this with Spring Framework 5.2.1.RELEASE.
In addition, I don't believe that Spring Framework ever supported property placeholders for @ActiveProfiles
.
Though, Spring Boot Test did at one point set the spring.profiles.active
system property which would result in nested placeholders being resolved against the Spring Environment
.
Thus, perhaps this change in behavior is related to Spring Boot and not Spring Framework.
@wilkinsona, is this perhaps related to https://github.com/spring-projects/spring-boot/issues/19788?
Comment From: wilkinsona
I don't think so. That issue was fixed in Spring Boot 2.1 which uses Framework 5.1. @icyerasor If you're using Spring Boot, what versions were involved?
Comment From: sbrannen
@wilkinsona, on a hunch, I'd say https://github.com/spring-projects/spring-boot/commit/49921d65acd29a9704c2dd54ef405d6654dcb321 introduced the change in behavior as an unintentional side effect.
I'll see if I can throw together some tests to prove or disprove it.
Comment From: sbrannen
Using Spring Boot 2.3.9.RELEASE
as-is, property placeholders in profiles configured via @ActiveProfiles
are replaced.
The same is true for Spring Boot 2.3.9.RELEASE
using Spring Framework 5.3.4
.
Property placeholder replacement stops working with Spring Boot 2.4.0
(and continues not to work with Boot 2.4.3
).
Thus something must have changed in Spring Boot 2.4.
@wilkinsona and @philwebb, would you mind taking this over in Boot's issue tracker?
Comment From: wilkinsona
If @icyerasor confirms they're using Boot then we should definitely transfer this over. If they're not then I guess we have two changes to track down somehow and we should probably open a separate Boot issue.
Comment From: icyerasor
Hi there, sorry was away over the weekend.. @wilkinsona yes we're using Boot / spring-boot-starter-test (2.4.2).
@sbrannen sorry for the confusion; should have probably stated this to begin with, but just saw @ActiveProfiles
from spring-test and thus blamed it 😅
Comment From: mbhave
I am able to reproduce what @sbrannen described. It must be related to the config data changes because it works with 2.4 if spring.config.use-legacy-processing
is set to true
.
What I found odd was that with 2.3.x too, environment.getActiveProfiles()
contains ${testprofiles.active:test}
. But it also contains test
which is why it works. @sbrannen Is ${testprofiles.active:test}
in the environment's active profiles expected behavior?
Comment From: sbrannen
With 2.3.9, if I run my test with -Dtestprofiles.active=integrationtest
and print out the active profiles, I see the following.
[${testprofiles.active:test}, integrationtest]
So I'm seeing the same behavior as you, which I hadn't noticed before.
To answer your question, no I would not expect to see ${testprofiles.active:test}
registered as an active profile.
So part of the mystery is why the placeholder expression and resolved placeholder both end up as registered active profiles.
The other side of the story involves whether resolution of property placeholders in @ActiveProfiles
was ever an intentional feature of Spring Boot Test. I can imagine that it was an accident, and yet some users may have come to depend on it. So perhaps the Spring Boot team wishes to reinstate that behavior. Another option would be investigating introducing that support in spring-test
.
Thoughts?
Comment From: sbrannen
It must be related to the config data changes because it works with 2.4 if
spring.config.use-legacy-processing
is set totrue
.
By the way, good catch on that!
Comment From: sbrannen
Another thing to keep in mind is the MergedContextConfiguration
(MCC), specifically regarding what active profiles are being stored in the MCC.
I suppose the unresolved property placeholder should be stored in the MCC and then only resolved once actually adding it to the Environment
-- resolved against properties available in the Environment
at that point in time.
Comment From: mbhave
Another option would be investigating introducing that support in spring-test.
oh I thought this was something spring-test
also supported. I am not sure if Spring Boot's support is intentional or by accident. It also gets tricky if the property that is resolved by @ActiveProfiles
lives in a profile-specific
file such as application-dev.yml
.
Flagging for team attention to see if the rest of the team thinks that placeholder resolution in @ActiveProfiles
was intentional and something that we should support.
Comment From: wilkinsona
I can't remember for certain, but given that we don't have any tests for it, I would assume that it was not intentional. If it's not supported by spring-test
then I would lean towards not supporting it in Boot.
Comment From: mbhave
We discussed this on the team call and we have decided to follow Spring Framework and not support placeholders in @ActiveProfiles
. This is not a regression because it happened to work by accident before 2.4.x and the behavior is neither tested nor documented.