From e2b33b0dbcf83343c63d4056d96d92d5a987ccb4 Mon Sep 17 00:00:00 2001 From: Mohak Nagaraju <98132980+Mohak-Nagaraju@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:19:37 -0400 Subject: [PATCH] Document that spring.profiles.active is ignored by TCF The Test Context Framework does not honor the spring.profiles.active system property when determining active profiles for a test class. This commit documents that behavior in the @ActiveProfiles and DefaultActiveProfilesResolver Javadoc, as well as in the reference manual. A SystemPropertyActiveProfilesResolver example is also added showing how to allow spring.profiles.active to override @ActiveProfiles. Closes gh-36269 Signed-off-by: Mohak Nagaraju <98132980+Mohak-Nagaraju@users.noreply.github.com> --- .../annotation-activeprofiles.adoc | 7 ++ .../ctx-management/env-profiles.adoc | 72 +++++++++++++++++++ .../test/context/ActiveProfiles.java | 10 +++ .../DefaultActiveProfilesResolver.java | 6 ++ 4 files changed, 95 insertions(+) diff --git a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-activeprofiles.adoc b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-activeprofiles.adoc index f6723c30f5d2..c68bf29dd9b7 100644 --- a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-activeprofiles.adoc +++ b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-activeprofiles.adoc @@ -72,6 +72,13 @@ bean definition profiles programmatically by implementing a custom xref:testing/testcontext-framework/ctx-management/env-profiles.adoc#testcontext-ctx-management-env-profiles-ActiveProfilesResolver[`ActiveProfilesResolver`] and registering it by using the `resolver` attribute of `@ActiveProfiles`. +NOTE: When `@ActiveProfiles` is declared on a test class, the `spring.profiles.active` +property (whether configured as a JVM system property or environment variable) is not +taken into account by the Test Context Framework when determining active profiles. If +you need to allow `spring.profiles.active` to override the profiles configured via +`@ActiveProfiles`, you can implement a custom `ActiveProfilesResolver` as described in +xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[Context Configuration with Environment Profiles]. + See xref:testing/testcontext-framework/ctx-management/env-profiles.adoc[Context Configuration with Environment Profiles], xref:testing/testcontext-framework/support-classes.adoc#testcontext-junit-jupiter-nested-test-configuration[`@Nested` test class configuration], and the {spring-framework-api}/test/context/ActiveProfiles.html[`@ActiveProfiles`] javadoc for diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/env-profiles.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/env-profiles.adoc index ea0c505e6643..fb997f5c6bd0 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/env-profiles.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/env-profiles.adoc @@ -543,3 +543,75 @@ Kotlin:: ---- ====== +The following example demonstrates how to implement and register a custom +`SystemPropertyOverrideActiveProfilesResolver` that allows the `spring.profiles.active` +property (whether configured as a JVM system property or environment variable) to +override profiles configured via `@ActiveProfiles`: + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- + // profiles resolved programmatically via a custom resolver that + // allows "spring.profiles.active" to override @ActiveProfiles + @ActiveProfiles( + resolver = SystemPropertyOverrideActiveProfilesResolver.class, + inheritProfiles = false) + class TransferServiceTest extends AbstractIntegrationTest { + // test body + } +---- + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +---- + // profiles resolved programmatically via a custom resolver that + // allows "spring.profiles.active" to override @ActiveProfiles + @ActiveProfiles( + resolver = SystemPropertyOverrideActiveProfilesResolver::class, + inheritProfiles = false) + class TransferServiceTest : AbstractIntegrationTest() { + // test body + } +---- +====== + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- + public class SystemPropertyOverrideActiveProfilesResolver implements ActiveProfilesResolver { + + @Override + public String[] resolve(Class testClass) { + String profiles = System.getProperty("spring.profiles.active"); + if (profiles != null && !profiles.isBlank()) { + return profiles.split(","); + } + return new DefaultActiveProfilesResolver().resolve(testClass); + } + } +---- + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +---- + class SystemPropertyOverrideActiveProfilesResolver : ActiveProfilesResolver { + + override fun resolve(testClass: Class<*>): Array { + val profiles = System.getProperty("spring.profiles.active") + if (!profiles.isNullOrBlank()) { + return profiles.split(",").toTypedArray() + } + return DefaultActiveProfilesResolver().resolve(testClass) + } + } +---- +====== + diff --git a/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java b/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java index 6b0e9d5b9cb0..473ca7a5702b 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java +++ b/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java @@ -37,6 +37,16 @@ *

This annotation will be inherited from an enclosing test class by default. * See {@link NestedTestConfiguration @NestedTestConfiguration} for details. * + *

Note that when {@code @ActiveProfiles} is declared on a test class, the + * {@code spring.profiles.active} property (whether configured as a JVM system + * property or environment variable) is not taken into account by the Test Context + * Framework when determining active profiles. If you need to allow + * {@code spring.profiles.active} to override the profiles configured via + * {@code @ActiveProfiles}, you can implement a custom {@link ActiveProfilesResolver} + * and register it via the {@link #resolver} attribute. See + * Context Configuration with Environment Profiles in the reference manual + * for further details and examples. + * * @author Sam Brannen * @since 3.1 * @see SmartContextLoader diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java b/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java index 71a33b00b991..826939718309 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java @@ -32,6 +32,12 @@ * configured declaratively via {@link ActiveProfiles#profiles} or * {@link ActiveProfiles#value}. * + *

Note that the {@code spring.profiles.active} property (whether configured + * as a JVM system property or environment variable) is not taken into account by + * this resolver. If you need to allow {@code spring.profiles.active} to override + * profiles configured via {@link ActiveProfiles}, you can implement a custom + * {@link ActiveProfilesResolver} and register it via {@link ActiveProfiles#resolver}. + * * @author Sam Brannen * @since 4.1 * @see ActiveProfiles