diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc index 6678e834c58..ca26bfa32d5 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/ctx-management/dynamic-property-sources.adoc @@ -2,39 +2,51 @@ = Context Configuration with Dynamic Property Sources The Spring TestContext Framework provides support for _dynamic_ properties via the -`@DynamicPropertySource` annotation and the `DynamicPropertyRegistry`. +`DynamicPropertyRegistry`, the `@DynamicPropertySource` annotation, and the +`DynamicPropertyRegistrar` API. [NOTE] ==== -The `@DynamicPropertySource` annotation and its supporting infrastructure were originally -designed to allow properties from {testcontainers-site}[Testcontainers] based tests to be -exposed easily to Spring integration tests. However, this feature may be used with any -form of external resource whose lifecycle is managed outside the test's -`ApplicationContext` or with beans whose lifecycle is managed by the test's -`ApplicationContext`. +The dynamic property source infrastructure was originally designed to allow properties +from {testcontainers-site}[Testcontainers] based tests to be exposed easily to Spring +integration tests. However, these features may be used with any form of external resource +whose lifecycle is managed outside the test's `ApplicationContext` or with beans whose +lifecycle is managed by the test's `ApplicationContext`. ==== + +[[testcontext-ctx-management-dynamic-property-sources-precedence]] +== Precedence + +Dynamic properties have higher precedence than those loaded from `@TestPropertySource`, +the operating system's environment, Java system properties, or property sources added by +the application declaratively by using `@PropertySource` or programmatically. Thus, +dynamic properties can be used to selectively override properties loaded via +`@TestPropertySource`, system property sources, and application property sources. + + +[[testcontext-ctx-management-dynamic-property-sources-dynamic-property-registry]] +== `DynamicPropertyRegistry` + +A `DynamicPropertyRegistry` is used to add _name-value_ pairs to the `Environment`. +Values are dynamic and provided via a `Supplier` which is only invoked when the property +is resolved. Typically, method references are used to supply values. The following +sections provide examples of how to use the `DynamicPropertyRegistry`. + + +[[testcontext-ctx-management-dynamic-property-sources-dynamic-property-source]] +== `@DynamicPropertySource` + In contrast to the xref:testing/testcontext-framework/ctx-management/property-sources.adoc[`@TestPropertySource`] annotation that is applied at the class level, `@DynamicPropertySource` can be applied to -`static` methods in integration test classes or to `@Bean` methods in test -`@Configuration` classes in order to add properties with dynamic values to the set of -`PropertySources` in the `Environment` for the `ApplicationContext` loaded for the -integration test. - -A `DynamicPropertyRegistry` is used to add _name-value_ pairs to the `Environment`. -Values are dynamic and provided via a `Supplier` which is only invoked when the property -is resolved. Typically, method references are used to supply values. +`static` methods in integration test classes in order to add properties with dynamic +values to the set of `PropertySources` in the `Environment` for the `ApplicationContext` +loaded for the integration test. Methods in integration test classes that are annotated with `@DynamicPropertySource` must -be `static` and must accept a single `DynamicPropertyRegistry` argument. - -`@Bean` methods annotated with `@DynamicPropertySource` may either accept an argument of -type `DynamicPropertyRegistry` or access a `DynamicPropertyRegistry` instance autowired -into their enclosing `@Configuration` class. Note, however, that `@Bean` methods which -interact with a `DynamicPropertyRegistry` are not required to be annotated with -`@DynamicPropertySource` unless they need to enforce eager initialization of the bean -within the context. See the class-level javadoc for `DynamicPropertyRegistry` for details. +be `static` and must accept a single `DynamicPropertyRegistry` argument. See the +class-level javadoc for `DynamicPropertyRegistry` for further details. [TIP] ==== @@ -107,11 +119,33 @@ Kotlin:: ---- ====== -The following example demonstrates how to use `DynamicPropertyRegistry` and -`@DynamicPropertySource` with a `@Bean` method. The `api.url` property can be accessed -via Spring's `Environment` abstraction or injected directly into other Spring-managed -components – for example, via `@Value("${api.url}")`. The value of the `api.url` property -will be dynamically retrieved from the `ApiServer` bean. + +[[testcontext-ctx-management-dynamic-property-sources-dynamic-property-registrar]] +== `DynamicPropertyRegistrar` + +As an alternative to implementing `@DynamicPropertySource` methods in integration test +classes, you can register implementations of the `DynamicPropertyRegistrar` API as beans +within the test's `ApplicationContext`. Doing so allows you to support additional use +cases that are not possible with a `@DynamicPropertySource` method. For example, since a +`DynamicPropertyRegistrar` is itself a bean in the `ApplicationContext`, it can interact +with other beans in the context and register dynamic properties that are sourced from +those beans. + +Any bean in a test's `ApplicationContext` that implements the `DynamicPropertyRegistrar` +interface will be automatically detected and eagerly initialized before the singleton +pre-instantiation phase, and the `accept()` methods of such beans will be invoked with a +`DynamicPropertyRegistry` that performs the actual dynamic property registration on +behalf of the registrar. + +WARNING: Any interaction with other beans results in eager initialization of those other +beans and their dependencies. + +The following example demonstrates how to implement a `DynamicPropertyRegistrar` as a +lambda expression that registers a dynamic property for the `ApiServer` bean. The +`api.url` property can be accessed via Spring's `Environment` abstraction or injected +directly into other Spring-managed components – for example, via `@Value("${api.url}")`, +and the value of the `api.url` property will be dynamically retrieved from the +`ApiServer` bean. [tabs] ====== @@ -123,11 +157,13 @@ Java:: class TestConfig { @Bean - @DynamicPropertySource - ApiServer apiServer(DynamicPropertyRegistry registry) { - ApiServer apiServer = new ApiServer(); - registry.add("api.url", apiServer::getUrl); - return apiServer; + ApiServer apiServer() { + return new ApiServer(); + } + + @Bean + DynamicPropertyRegistrar apiServerProperties(ApiServer apiServer) { + return registry -> registry.add("api.url", apiServer::getUrl); } } ---- @@ -140,27 +176,14 @@ Kotlin:: class TestConfig { @Bean - @DynamicPropertySource - fun apiServer(registry: DynamicPropertyRegistry): ApiServer { - val apiServer = ApiServer() - registry.add("api.url", apiServer::getUrl) - return apiServer + fun apiServer(): ApiServer { + return ApiServer() + } + + @Bean + fun apiServerProperties(apiServer: ApiServer): DynamicPropertyRegistrar { + return registry -> registry.add("api.url", apiServer::getUrl) } } ---- ====== - -NOTE: The use of `@DynamicPropertySource` on the `@Bean` method is optional and results -in the `ApiServer` bean being eagerly initialized so that other beans in the context can -be given access to the dynamic properties sourced from the `ApiServer` bean when those -other beans are initialized. - -[[testcontext-ctx-management-dynamic-property-sources-precedence]] -== Precedence - -Dynamic properties have higher precedence than those loaded from `@TestPropertySource`, -the operating system's environment, Java system properties, or property sources added by -the application declaratively by using `@PropertySource` or programmatically. Thus, -dynamic properties can be used to selectively override properties loaded via -`@TestPropertySource`, system property sources, and application property sources. - diff --git a/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistrar.java b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistrar.java new file mode 100644 index 00000000000..e30fe648054 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistrar.java @@ -0,0 +1,87 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context; + +/** + * Registrar that is used to add properties with dynamically resolved values to + * the {@code Environment} via a {@link DynamicPropertyRegistry}. + * + *

Any bean in a test's {@code ApplicationContext} that implements the + * {@code DynamicPropertyRegistrar} interface will be automatically detected and + * eagerly initialized before the singleton pre-instantiation phase, and the + * {@link #accept} methods of such beans will be invoked with a + * {@code DynamicPropertyRegistry} that performs the actual dynamic property + * registration on behalf of the registrar. + * + *

This is an alternative to implementing + * {@link DynamicPropertySource @DynamicPropertySource} methods in integration + * test classes and supports additional use cases that are not possible with a + * {@code @DynamicPropertySource} method. For example, since a + * {@code DynamicPropertyRegistrar} is itself a bean in the {@code ApplicationContext}, + * it can interact with other beans in the context and register dynamic properties + * that are sourced from those beans. Note, however, that any interaction with + * other beans results in eager initialization of those other beans and their + * dependencies. + * + *

Precedence

+ * + *

Dynamic properties have higher precedence than those loaded from + * {@link TestPropertySource @TestPropertySource}, the operating system's + * environment, Java system properties, or property sources added by the + * application declaratively by using + * {@link org.springframework.context.annotation.PropertySource @PropertySource} + * or programmatically. Thus, dynamic properties can be used to selectively + * override properties loaded via {@code @TestPropertySource}, system property + * sources, and application property sources. + * + *

Example

+ * + *

The following example demonstrates how to implement a + * {@code DynamicPropertyRegistrar} as a lambda expression that registers a + * dynamic property for the {@code ApiServer} bean. Other beans in the + * {@code ApplicationContext} can access the {@code api.url} property which is + * dynamically retrieved from the {@code ApiServer} bean — for example, + * via {@code @Value("${api.url}")}. + * + *

+ * @Configuration
+ * class TestConfig {
+ *
+ *     @Bean
+ *     ApiServer apiServer() {
+ *         return new ApiServer();
+ *     }
+ *
+ *     @Bean
+ *     DynamicPropertyRegistrar apiServerProperties(ApiServer apiServer) {
+ *         return registry -> registry.add("api.url", apiServer::getUrl);
+ *     }
+ *
+ * }
+ * + * @author Sam Brannen + * @since 6.2 + * @see DynamicPropertySource + * @see DynamicPropertyRegistry + * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons() + */ +@FunctionalInterface +public interface DynamicPropertyRegistrar { + + void accept(DynamicPropertyRegistry registry); + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistry.java b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistry.java index cc73b838a5b..2aa2984949c 100644 --- a/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistry.java +++ b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertyRegistry.java @@ -27,22 +27,18 @@ import java.util.function.Supplier; * test classes. * *

As of Spring Framework 6.2, a {@code DynamicPropertyRegistry} is also - * registered as a singleton bean in the test's {@code ApplicationContext}. This - * allows a {@code DynamicPropertyRegistry} to be autowired into a - * {@code @Configuration} class or supplied to a {@code @Bean} method as an - * argument, making it possible to register a dynamic property from within a test's - * {@code ApplicationContext}. For example, a {@code @Bean} method can register - * a property whose value is dynamically sourced from the bean that the method - * returns. Note that such a {@code @Bean} method can optionally be annotated - * with {@code @DynamicPropertySource} to enforce eager initialization of the - * bean within the context, thereby ensuring that any dynamic properties sourced - * from that bean are available to other singleton beans within the context. - * See {@link DynamicPropertySource @DynamicPropertySource} for an example. + * supplied to {@link DynamicPropertyRegistrar} beans in the test's + * {@code ApplicationContext}, making it possible to register dynamic properties + * based on beans in the context. For example, a {@code @Bean} method can return + * a {@code DynamicPropertyRegistrar} that registers a property whose value is + * dynamically sourced from another bean in the context. See the documentation + * for {@code DynamicPropertyRegistrar} for an example. * * @author Phillip Webb * @author Sam Brannen * @since 5.2.5 * @see DynamicPropertySource + * @see DynamicPropertyRegistrar */ public interface DynamicPropertyRegistry { diff --git a/spring-test/src/main/java/org/springframework/test/context/DynamicPropertySource.java b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertySource.java index a491abe3949..919569d025d 100644 --- a/spring-test/src/main/java/org/springframework/test/context/DynamicPropertySource.java +++ b/spring-test/src/main/java/org/springframework/test/context/DynamicPropertySource.java @@ -24,42 +24,35 @@ import java.lang.annotation.Target; /** * {@code @DynamicPropertySource} is an annotation that can be applied to static - * methods in integration test classes or to {@code @Bean} methods in test - * {@code @Configuration} classes in order to add properties with dynamic values - * to the {@code Environment}'s set of {@code PropertySources}. + * methods in integration test classes in order to add properties with dynamic + * values to the {@code Environment}'s set of {@code PropertySources}. + * + *

Alternatively, dynamic properties can be added to the {@code Environment} + * by special beans in the test's {@code ApplicationContext}. See + * {@link DynamicPropertyRegistrar} for details. * *

This annotation and its supporting infrastructure were originally designed * to allow properties from * Testcontainers based tests to be * exposed easily to Spring integration tests. However, this feature may be used * with any form of external resource whose lifecycle is managed outside the - * test's {@code ApplicationContext} or with beans whose lifecycle is managed by - * the test's {@code ApplicationContext}. + * test's {@code ApplicationContext}. * - *

{@code @DynamicPropertySource}-annotated methods use a - * {@code DynamicPropertyRegistry} to add name-value pairs to the - * {@code Environment}'s set of {@code PropertySources}. Values are dynamic and - * provided via a {@link java.util.function.Supplier} which is only invoked when - * the property is resolved. Typically, method references are used to supply values, - * as in the example below. + *

{@code @DynamicPropertySource} methods use a {@link DynamicPropertyRegistry} + * to add name-value pairs to the {@code Environment}'s set of + * {@code PropertySources}. Values are dynamic and provided via a + * {@link java.util.function.Supplier} which is only invoked when the property is + * resolved. Typically, method references are used to supply values, as in the + * example below. * *

Methods in integration test classes that are annotated with * {@code @DynamicPropertySource} must be {@code static} and must accept a single - * {@link DynamicPropertyRegistry} argument. - * - *

{@code @Bean} methods annotated with {@code @DynamicPropertySource} may - * either accept an argument of type {@code DynamicPropertyRegistry} or access a - * {@code DynamicPropertyRegistry} instance autowired into their enclosing - * {@code @Configuration} class. Note, however, that {@code @Bean} methods which - * interact with a {@code DynamicPropertyRegistry} are not required to be annotated - * with {@code @DynamicPropertySource} unless they need to enforce eager - * initialization of the bean within the context. - * See {@link DynamicPropertyRegistry} for details. + * {@code DynamicPropertyRegistry} argument. * *

Dynamic properties from methods annotated with {@code @DynamicPropertySource} * will be inherited from enclosing test classes, analogous to inheritance - * from superclasses and interfaces. - * See {@link NestedTestConfiguration @NestedTestConfiguration} for details. + * from superclasses and interfaces. See + * {@link NestedTestConfiguration @NestedTestConfiguration} for details. * *

NOTE: if you use {@code @DynamicPropertySource} in a base * class and discover that tests in subclasses fail because the dynamic properties @@ -69,6 +62,7 @@ import java.lang.annotation.Target; * correct dynamic properties. * *

Precedence

+ * *

Dynamic properties have higher precedence than those loaded from * {@link TestPropertySource @TestPropertySource}, the operating system's * environment, Java system properties, or property sources added by the @@ -103,28 +97,11 @@ import java.lang.annotation.Target; * } * } * - *

The following example demonstrates how to use {@code @DynamicPropertySource} - * with a {@code @Bean} method. Beans in the {@code ApplicationContext} can - * access the {@code api.url} property which is dynamically retrieved from the - * {@code ApiServer} bean. - * - *

- * @Configuration
- * class TestConfig {
- *
- *     @Bean
- *     @DynamicPropertySource
- *     ApiServer apiServer(DynamicPropertyRegistry registry) {
- *         ApiServer apiServer = new ApiServer();
- *         registry.add("api.url", apiServer::getUrl);
- *         return apiServer;
- *     }
- * }
- * * @author Phillip Webb * @author Sam Brannen * @since 5.2.5 * @see DynamicPropertyRegistry + * @see DynamicPropertyRegistrar * @see ContextConfiguration * @see TestPropertySource * @see org.springframework.core.env.PropertySource diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DefaultDynamicPropertyRegistry.java b/spring-test/src/main/java/org/springframework/test/context/support/DefaultDynamicPropertyRegistry.java deleted file mode 100644 index e079c379541..00000000000 --- a/spring-test/src/main/java/org/springframework/test/context/support/DefaultDynamicPropertyRegistry.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.support; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Supplier; - -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.util.Assert; - -/** - * Default {@link DynamicPropertyRegistry} implementation. - * - * @author Sam Brannen - * @since 6.2 - */ -final class DefaultDynamicPropertyRegistry implements DynamicPropertyRegistry { - - final Map> valueSuppliers = Collections.synchronizedMap(new LinkedHashMap<>()); - - private final ConfigurableEnvironment environment; - - private final boolean lazilyRegisterPropertySource; - - private final Lock propertySourcesLock = new ReentrantLock(); - - - DefaultDynamicPropertyRegistry(ConfigurableEnvironment environment, boolean lazilyRegisterPropertySource) { - this.environment = environment; - this.lazilyRegisterPropertySource = lazilyRegisterPropertySource; - } - - - @Override - public void add(String name, Supplier valueSupplier) { - Assert.hasText(name, "'name' must not be null or blank"); - Assert.notNull(valueSupplier, "'valueSupplier' must not be null"); - if (this.lazilyRegisterPropertySource) { - ensurePropertySourceIsRegistered(); - } - this.valueSuppliers.put(name, valueSupplier); - } - - private void ensurePropertySourceIsRegistered() { - MutablePropertySources propertySources = this.environment.getPropertySources(); - this.propertySourcesLock.lock(); - try { - PropertySource ps = propertySources.get(DynamicValuesPropertySource.PROPERTY_SOURCE_NAME); - if (ps == null) { - propertySources.addFirst(new DynamicValuesPropertySource(this.valueSuppliers)); - } - } - finally { - this.propertySourcesLock.unlock(); - } - } - -} diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizer.java b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizer.java index 156d51eeabc..bb2c12488e2 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizer.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizer.java @@ -26,35 +26,32 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.MutablePropertySources; import org.springframework.lang.Nullable; import org.springframework.test.context.ContextCustomizer; import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.MergedContextConfiguration; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** * {@link ContextCustomizer} which supports - * {@link DynamicPropertySource @DynamicPropertySource} methods and registers a - * {@link DynamicPropertyRegistry} as a singleton bean in the container for use - * in {@code @Configuration} classes and {@code @Bean} methods. + * {@link org.springframework.test.context.DynamicPropertySource @DynamicPropertySource} + * methods in test classes and registers a {@link DynamicPropertyRegistrarBeanInitializer} + * in the container to eagerly initialize + * {@link org.springframework.test.context.DynamicPropertyRegistrar DynamicPropertyRegistrar} + * beans. * * @author Phillip Webb * @author Sam Brannen * @since 5.2.5 * @see DynamicPropertiesContextCustomizerFactory * @see DefaultDynamicPropertyRegistry - * @see DynamicPropertySourceBeanInitializer + * @see DynamicPropertyRegistrarBeanInitializer */ class DynamicPropertiesContextCustomizer implements ContextCustomizer { - private static final String DYNAMIC_PROPERTY_REGISTRY_BEAN_NAME = - DynamicPropertiesContextCustomizer.class.getName() + ".dynamicPropertyRegistry"; - - private static final String DYNAMIC_PROPERTY_SOURCE_BEAN_INITIALIZER_BEAN_NAME = - DynamicPropertiesContextCustomizer.class.getName() + ".dynamicPropertySourceBeanInitializer"; + private static final String DYNAMIC_PROPERTY_REGISTRAR_BEAN_INITIALIZER_BEAN_NAME = + DynamicPropertiesContextCustomizer.class.getName() + ".dynamicPropertyRegistrarBeanInitializer"; private final Set methods; @@ -68,29 +65,25 @@ class DynamicPropertiesContextCustomizer implements ContextCustomizer { @Override public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) { - ConfigurableEnvironment environment = context.getEnvironment(); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); if (!(beanFactory instanceof BeanDefinitionRegistry beanDefinitionRegistry)) { throw new IllegalStateException("BeanFactory must be a BeanDefinitionRegistry"); } - DefaultDynamicPropertyRegistry dynamicPropertyRegistry = - new DefaultDynamicPropertyRegistry(environment, this.methods.isEmpty()); - beanFactory.registerSingleton(DYNAMIC_PROPERTY_REGISTRY_BEAN_NAME, dynamicPropertyRegistry); - - if (!beanDefinitionRegistry.containsBeanDefinition(DYNAMIC_PROPERTY_SOURCE_BEAN_INITIALIZER_BEAN_NAME)) { - BeanDefinition beanDefinition = new RootBeanDefinition(DynamicPropertySourceBeanInitializer.class); + if (!beanDefinitionRegistry.containsBeanDefinition(DYNAMIC_PROPERTY_REGISTRAR_BEAN_INITIALIZER_BEAN_NAME)) { + BeanDefinition beanDefinition = new RootBeanDefinition(DynamicPropertyRegistrarBeanInitializer.class); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); beanDefinitionRegistry.registerBeanDefinition( - DYNAMIC_PROPERTY_SOURCE_BEAN_INITIALIZER_BEAN_NAME, beanDefinition); + DYNAMIC_PROPERTY_REGISTRAR_BEAN_INITIALIZER_BEAN_NAME, beanDefinition); } if (!this.methods.isEmpty()) { - MutablePropertySources propertySources = environment.getPropertySources(); - propertySources.addFirst(new DynamicValuesPropertySource(dynamicPropertyRegistry.valueSuppliers)); + ConfigurableEnvironment environment = context.getEnvironment(); + DynamicValuesPropertySource propertySource = DynamicValuesPropertySource.getOrCreate(environment); + DynamicPropertyRegistry registry = propertySource.dynamicPropertyRegistry; this.methods.forEach(method -> { ReflectionUtils.makeAccessible(method); - ReflectionUtils.invokeMethod(method, null, dynamicPropertyRegistry); + ReflectionUtils.invokeMethod(method, null, registry); }); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizerFactory.java b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizerFactory.java index f25a7335eef..ddd11ffe6a9 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizerFactory.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertiesContextCustomizerFactory.java @@ -27,15 +27,14 @@ import org.springframework.core.annotation.MergedAnnotations; import org.springframework.lang.Nullable; import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextCustomizerFactory; -import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestContextAnnotationUtils; /** * {@link ContextCustomizerFactory} which supports - * {@link DynamicPropertySource @DynamicPropertySource} methods and the - * registration of a {@link DynamicPropertyRegistry} as a singleton bean in the - * container for use in {@code @Configuration} classes and {@code @Bean} methods. + * {@link DynamicPropertySource @DynamicPropertySource} methods in test classes + * and {@link org.springframework.test.context.DynamicPropertyRegistrar + * DynamicPropertyRegistrar} beans in the container. * * @author Phillip Webb * @author Sam Brannen diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer.java b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer.java new file mode 100644 index 00000000000..ecfa1d5736b --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer.java @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.support; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.beans.factory.BeanFactoryInitializer; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.lang.Nullable; +import org.springframework.test.context.DynamicPropertyRegistrar; +import org.springframework.test.context.DynamicPropertyRegistry; + +/** + * Internal component which eagerly initializes {@link DynamicPropertyRegistrar} + * beans. + * + * @author Sam Brannen + * @since 6.2 + */ +class DynamicPropertyRegistrarBeanInitializer implements BeanFactoryInitializer, EnvironmentAware { + + private static final Log logger = LogFactory.getLog(DynamicPropertyRegistrarBeanInitializer.class); + + + @Nullable + private ConfigurableEnvironment environment; + + + @Override + public void setEnvironment(Environment environment) { + if (!(environment instanceof ConfigurableEnvironment configurableEnvironment)) { + throw new IllegalArgumentException("Environment must be a ConfigurableEnvironment"); + } + this.environment = configurableEnvironment; + } + + @Override + public void initialize(ListableBeanFactory beanFactory) { + if (this.environment == null) { + throw new IllegalStateException("Environment is required"); + } + String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( + beanFactory, DynamicPropertyRegistrar.class); + if (beanNames.length > 0) { + DynamicValuesPropertySource propertySource = DynamicValuesPropertySource.getOrCreate(this.environment); + DynamicPropertyRegistry registry = propertySource.dynamicPropertyRegistry; + for (String name : beanNames) { + if (logger.isDebugEnabled()) { + logger.debug("Eagerly initializing DynamicPropertyRegistrar bean '%s'".formatted(name)); + } + DynamicPropertyRegistrar registrar = beanFactory.getBean(name, DynamicPropertyRegistrar.class); + registrar.accept(registry); + } + } + } + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertySourceBeanInitializer.java b/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertySourceBeanInitializer.java deleted file mode 100644 index d30ba11a482..00000000000 --- a/spring-test/src/main/java/org/springframework/test/context/support/DynamicPropertySourceBeanInitializer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.test.context.support; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.BeanFactoryInitializer; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.test.context.DynamicPropertySource; - -/** - * Internal component which eagerly initializes beans created by {@code @Bean} - * factory methods annotated with {@link DynamicPropertySource @DynamicPropertySource}. - * - * @author Sam Brannen - * @since 6.2 - */ -class DynamicPropertySourceBeanInitializer implements BeanFactoryInitializer { - - private static final Log logger = LogFactory.getLog(DynamicPropertySourceBeanInitializer.class); - - - @Override - public void initialize(ListableBeanFactory beanFactory) { - for (String name : beanFactory.getBeanNamesForAnnotation(DynamicPropertySource.class)) { - if (logger.isDebugEnabled()) { - logger.debug("Eagerly initializing @DynamicPropertySource bean '%s'".formatted(name)); - } - beanFactory.getBean(name); - } - } - -} diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DynamicValuesPropertySource.java b/spring-test/src/main/java/org/springframework/test/context/support/DynamicValuesPropertySource.java index b595e7e2a1e..bbe560152ea 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DynamicValuesPropertySource.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DynamicValuesPropertySource.java @@ -17,11 +17,17 @@ package org.springframework.test.context.support; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Supplier; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; import org.springframework.lang.Nullable; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.util.Assert; import org.springframework.util.function.SupplierUtils; /** @@ -36,9 +42,20 @@ class DynamicValuesPropertySource extends MapPropertySource { static final String PROPERTY_SOURCE_NAME = "Dynamic Test Properties"; + final DynamicPropertyRegistry dynamicPropertyRegistry; + + + DynamicValuesPropertySource() { + this(Collections.synchronizedMap(new LinkedHashMap<>())); + } DynamicValuesPropertySource(Map> valueSuppliers) { super(PROPERTY_SOURCE_NAME, Collections.unmodifiableMap(valueSuppliers)); + this.dynamicPropertyRegistry = (name, valueSupplier) -> { + Assert.hasText(name, "'name' must not be null or blank"); + Assert.notNull(valueSupplier, "'valueSupplier' must not be null"); + valueSuppliers.put(name, valueSupplier); + }; } @@ -48,4 +65,27 @@ class DynamicValuesPropertySource extends MapPropertySource { return SupplierUtils.resolve(super.getProperty(name)); } + + /** + * Get the {@code DynamicValuesPropertySource} registered in the environment + * or create and register a new {@code DynamicValuesPropertySource} in the + * environment. + */ + static DynamicValuesPropertySource getOrCreate(ConfigurableEnvironment environment) { + MutablePropertySources propertySources = environment.getPropertySources(); + PropertySource propertySource = propertySources.get(PROPERTY_SOURCE_NAME); + if (propertySource instanceof DynamicValuesPropertySource dynamicValuesPropertySource) { + return dynamicValuesPropertySource; + } + else if (propertySource == null) { + DynamicValuesPropertySource dynamicValuesPropertySource = new DynamicValuesPropertySource(); + propertySources.addFirst(dynamicValuesPropertySource); + return dynamicValuesPropertySource; + } + else { + throw new IllegalStateException("PropertySource with name '%s' must be a DynamicValuesPropertySource" + .formatted(PROPERTY_SOURCE_NAME)); + } + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertiesTestSuite.java b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertiesTestSuite.java index e2842bd53e5..a6fbe771c30 100644 --- a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertiesTestSuite.java +++ b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertiesTestSuite.java @@ -41,7 +41,7 @@ import org.junit.platform.suite.api.Suite; @Suite @SelectClasses( value = { - DynamicPropertyRegistryIntegrationTests.class, + DynamicPropertyRegistrarIntegrationTests.class, DynamicPropertySourceIntegrationTests.class }, names = { diff --git a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistryIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistrarIntegrationTests.java similarity index 57% rename from spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistryIntegrationTests.java rename to spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistrarIntegrationTests.java index c659f6f495b..477c4ab0265 100644 --- a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistryIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertyRegistrarIntegrationTests.java @@ -29,60 +29,77 @@ import org.springframework.core.env.MutablePropertySources; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatRuntimeException; /** - * Integration tests for {@link DynamicPropertyRegistry} bean support. + * Integration tests for {@link DynamicPropertyRegistrar} bean support. * * @author Sam Brannen * @since 6.2 * @see DynamicPropertySourceIntegrationTests */ @SpringJUnitConfig -@TestPropertySource(properties = "api.url: https://example.com/test") -class DynamicPropertyRegistryIntegrationTests { +@TestPropertySource(properties = "api.url.1: https://example.com/test") +class DynamicPropertyRegistrarIntegrationTests { - private static final String API_URL = "api.url"; + private static final String API_URL_1 = "api.url.1"; + private static final String API_URL_2 = "api.url.2"; + @Test + void customDynamicPropertyRegistryCanExistInApplicationContext( + @Autowired DynamicPropertyRegistry dynamicPropertyRegistry) { + + assertThatRuntimeException() + .isThrownBy(() -> dynamicPropertyRegistry.add("test", () -> "test")) + .withMessage("Boom!"); + } + @Test void dynamicPropertySourceOverridesTestPropertySource(@Autowired ConfigurableEnvironment env) { - assertApiUrlIsDynamic(env.getProperty(API_URL)); + assertApiUrlIsDynamic1(env.getProperty(API_URL_1)); MutablePropertySources propertySources = env.getPropertySources(); assertThat(propertySources.size()).isGreaterThanOrEqualTo(4); assertThat(propertySources.contains("Inlined Test Properties")).isTrue(); assertThat(propertySources.contains("Dynamic Test Properties")).isTrue(); - assertThat(propertySources.get("Inlined Test Properties").getProperty(API_URL)).isEqualTo("https://example.com/test"); - assertThat(propertySources.get("Dynamic Test Properties").getProperty(API_URL)).isEqualTo("https://example.com/dynamic"); + assertThat(propertySources.get("Inlined Test Properties").getProperty(API_URL_1)).isEqualTo("https://example.com/test"); + assertThat(propertySources.get("Dynamic Test Properties").getProperty(API_URL_1)).isEqualTo("https://example.com/dynamic/1"); + assertThat(propertySources.get("Dynamic Test Properties").getProperty(API_URL_2)).isEqualTo("https://example.com/dynamic/2"); } @Test - void testReceivesDynamicProperty(@Value("${api.url}") String apiUrl) { - assertApiUrlIsDynamic(apiUrl); + void testReceivesDynamicProperties(@Value("${api.url.1}") String apiUrl1, @Value("${api.url.2}") String apiUrl2) { + assertApiUrlIsDynamic1(apiUrl1); + assertApiUrlIsDynamic2(apiUrl2); } @Test void environmentInjectedServiceCanRetrieveDynamicProperty(@Autowired EnvironmentInjectedService service) { - assertApiUrlIsDynamic(service); + assertApiUrlIsDynamic1(service); } @Test void constructorInjectedServiceReceivesDynamicProperty(@Autowired ConstructorInjectedService service) { - assertApiUrlIsDynamic(service); + assertApiUrlIsDynamic1(service); } @Test void setterInjectedServiceReceivesDynamicProperty(@Autowired SetterInjectedService service) { - assertApiUrlIsDynamic(service); + assertApiUrlIsDynamic1(service); } - private static void assertApiUrlIsDynamic(ApiUrlClient service) { - assertApiUrlIsDynamic(service.getApiUrl()); + private static void assertApiUrlIsDynamic1(ApiUrlClient service) { + assertApiUrlIsDynamic1(service.getApiUrl()); } - private static void assertApiUrlIsDynamic(String apiUrl) { - assertThat(apiUrl).isEqualTo("https://example.com/dynamic"); + private static void assertApiUrlIsDynamic1(String apiUrl) { + assertThat(apiUrl).isEqualTo("https://example.com/dynamic/1"); + } + + private static void assertApiUrlIsDynamic2(String apiUrl) { + assertThat(apiUrl).isEqualTo("https://example.com/dynamic/2"); } @@ -90,16 +107,30 @@ class DynamicPropertyRegistryIntegrationTests { @Import({ EnvironmentInjectedService.class, ConstructorInjectedService.class, SetterInjectedService.class }) static class Config { - // Annotating this @Bean method with @DynamicPropertySource ensures that - // this bean will be instantiated before any other singleton beans in the + @Bean + ApiServer apiServer() { + return new ApiServer(); + } + + // Accepting ApiServer as a method argument ensures that the apiServer + // bean will be instantiated before any other singleton beans in the // context which further ensures that the dynamic "api.url" property is // available to all standard singleton beans. @Bean - @DynamicPropertySource - ApiServer apiServer(DynamicPropertyRegistry registry) { - ApiServer apiServer = new ApiServer(); - registry.add(API_URL, apiServer::getUrl); - return apiServer; + DynamicPropertyRegistrar apiServerProperties1(ApiServer apiServer) { + return registry -> registry.add(API_URL_1, () -> apiServer.getUrl() + "/1"); + } + + @Bean + DynamicPropertyRegistrar apiServerProperties2(ApiServer apiServer) { + return registry -> registry.add(API_URL_2, () -> apiServer.getUrl() + "/2"); + } + + @Bean + DynamicPropertyRegistry dynamicPropertyRegistry() { + return (name, valueSupplier) -> { + throw new RuntimeException("Boom!"); + }; } } @@ -120,7 +151,7 @@ class DynamicPropertyRegistryIntegrationTests { @Override public String getApiUrl() { - return this.env.getProperty(API_URL); + return this.env.getProperty(API_URL_1); } } @@ -129,7 +160,7 @@ class DynamicPropertyRegistryIntegrationTests { private final String apiUrl; - ConstructorInjectedService(@Value("${api.url}") String apiUrl) { + ConstructorInjectedService(@Value("${api.url.1}") String apiUrl) { this.apiUrl = apiUrl; } @@ -145,7 +176,7 @@ class DynamicPropertyRegistryIntegrationTests { @Autowired - void setApiUrl(@Value("${api.url}") String apiUrl) { + void setApiUrl(@Value("${api.url.1}") String apiUrl) { this.apiUrl = apiUrl; } diff --git a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertySourceIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertySourceIntegrationTests.java index 73a86f9dcb5..ba6d675e315 100644 --- a/spring-test/src/test/java/org/springframework/test/context/DynamicPropertySourceIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/DynamicPropertySourceIntegrationTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.env.ConfigurableEnvironment; @@ -30,14 +31,16 @@ import org.springframework.core.env.MutablePropertySources; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; /** - * Integration tests for {@link DynamicPropertySource @DynamicPropertySource}. + * Integration tests for {@link DynamicPropertySource @DynamicPropertySource} and + * {@link DynamicPropertyRegistrar} bean support. * * @author Phillip Webb * @author Sam Brannen - * @see DynamicPropertyRegistryIntegrationTests + * @see DynamicPropertyRegistrarIntegrationTests */ @SpringJUnitConfig @TestPropertySource(properties = "test.container.ip: test") @@ -46,6 +49,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; class DynamicPropertySourceIntegrationTests { private static final String TEST_CONTAINER_IP = "test.container.ip"; + private static final String MAGIC_WORD = "magic.word"; static { System.setProperty(TEST_CONTAINER_IP, "system"); @@ -54,8 +58,12 @@ class DynamicPropertySourceIntegrationTests { static final DemoContainer container = new DemoContainer(); @DynamicPropertySource - static void containerProperties(DynamicPropertyRegistry registry) { + static void containerPropertiesIpAddress(DynamicPropertyRegistry registry) { registry.add(TEST_CONTAINER_IP, container::getIpAddress); + } + + @DynamicPropertySource + static void containerPropertiesPort(DynamicPropertyRegistry registry) { registry.add("test.container.port", container::getPort); } @@ -65,6 +73,16 @@ class DynamicPropertySourceIntegrationTests { System.clearProperty(TEST_CONTAINER_IP); } + @Test + @DisplayName("A custom DynamicPropertyRegistry bean can exist in the ApplicationContext") + void customDynamicPropertyRegistryCanExistInApplicationContext( + @Autowired DynamicPropertyRegistry dynamicPropertyRegistry) { + + assertThatRuntimeException() + .isThrownBy(() -> dynamicPropertyRegistry.add("test", () -> "test")) + .withMessage("Boom!"); + } + @Test @DisplayName("@DynamicPropertySource overrides @TestPropertySource and JVM system property") void dynamicPropertySourceOverridesTestPropertySourceAndSystemProperty(@Autowired ConfigurableEnvironment env) { @@ -74,9 +92,11 @@ class DynamicPropertySourceIntegrationTests { assertThat(propertySources.contains("Inlined Test Properties")).isTrue(); assertThat(propertySources.contains("systemProperties")).isTrue(); assertThat(propertySources.get("Dynamic Test Properties").getProperty(TEST_CONTAINER_IP)).isEqualTo("127.0.0.1"); + assertThat(propertySources.get("Dynamic Test Properties").getProperty(MAGIC_WORD)).isEqualTo("enigma"); assertThat(propertySources.get("Inlined Test Properties").getProperty(TEST_CONTAINER_IP)).isEqualTo("test"); assertThat(propertySources.get("systemProperties").getProperty(TEST_CONTAINER_IP)).isEqualTo("system"); assertThat(env.getProperty(TEST_CONTAINER_IP)).isEqualTo("127.0.0.1"); + assertThat(env.getProperty(MAGIC_WORD)).isEqualTo("enigma"); } @Test @@ -90,6 +110,19 @@ class DynamicPropertySourceIntegrationTests { @Configuration @Import(Service.class) static class Config { + + @Bean + DynamicPropertyRegistrar magicWordProperties() { + return registry -> registry.add(MAGIC_WORD, () -> "enigma"); + } + + @Bean + DynamicPropertyRegistry dynamicPropertyRegistry() { + return (name, valueSupplier) -> { + throw new RuntimeException("Boom!"); + }; + } + } static class Service { diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/AbstractAotTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/AbstractAotTests.java index 99e746d8add..31a8ef5d8a1 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/AbstractAotTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/AbstractAotTests.java @@ -40,7 +40,7 @@ abstract class AbstractAotTests { "org/springframework/test/context/aot/samples/basic/BasicSpringJupiterImportedConfigTests__TestContext001_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/BasicSpringJupiterImportedConfigTests__TestContext001_BeanFactoryRegistrations.java", "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext001_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext001_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext001_BeanDefinitions.java", // BasicSpringJupiterSharedConfigTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext002_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext002_BeanDefinitions.java", @@ -51,7 +51,7 @@ abstract class AbstractAotTests { "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext002_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext002_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext002_ManagementBeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext002_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext002_BeanDefinitions.java", // BasicSpringJupiterTests -- not generated b/c already generated for BasicSpringJupiterSharedConfigTests. // BasicSpringJupiterTests.NestedTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext003_BeanDefinitions.java", @@ -63,28 +63,28 @@ abstract class AbstractAotTests { "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext003_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext003_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext003_ManagementBeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext003_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext003_BeanDefinitions.java", // BasicSpringTestNGTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext004_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext004_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests__TestContext004_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests__TestContext004_BeanFactoryRegistrations.java", "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext004_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext004_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext004_BeanDefinitions.java", // BasicSpringVintageTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext005_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext005_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests__TestContext005_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests__TestContext005_BeanFactoryRegistrations.java", "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext005_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext005_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext005_BeanDefinitions.java", // DisabledInAotRuntimeMethodLevelTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext006_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext006_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/DisabledInAotRuntimeMethodLevelTests__TestContext006_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/basic/DisabledInAotRuntimeMethodLevelTests__TestContext006_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/DisabledInAotRuntimeMethodLevelTests__TestContext006_BeanFactoryRegistrations.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext006_BeanDefinitions.java" + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext006_BeanDefinitions.java" }; Stream> scan() { diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java index d98478befd4..4ab72df7e6d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/TestContextAotGeneratorIntegrationTests.java @@ -395,7 +395,7 @@ class TestContextAotGeneratorIntegrationTests extends AbstractAotTests { "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext001_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext001_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext001_ManagementBeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext001_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext001_BeanDefinitions.java", // BasicSpringJupiterTests -- not generated b/c already generated for BasicSpringJupiterSharedConfigTests. // BasicSpringJupiterTests.NestedTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext002_BeanDefinitions.java", @@ -407,28 +407,28 @@ class TestContextAotGeneratorIntegrationTests extends AbstractAotTests { "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext002_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementConfiguration__TestContext002_BeanDefinitions.java", "org/springframework/test/context/aot/samples/management/ManagementMessageService__TestContext002_ManagementBeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext002_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext002_BeanDefinitions.java", // BasicSpringTestNGTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext003_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext003_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests__TestContext003_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/basic/BasicSpringTestNGTests__TestContext003_BeanFactoryRegistrations.java", "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext003_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext003_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext003_BeanDefinitions.java", // BasicSpringVintageTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext004_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext004_BeanDefinitions.java", "org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests__TestContext004_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/basic/BasicSpringVintageTests__TestContext004_BeanFactoryRegistrations.java", "org/springframework/test/context/aot/samples/basic/BasicTestConfiguration__TestContext004_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext004_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext004_BeanDefinitions.java", // SqlScriptsSpringJupiterTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext005_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext005_BeanDefinitions.java", "org/springframework/test/context/aot/samples/jdbc/SqlScriptsSpringJupiterTests__TestContext005_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/jdbc/SqlScriptsSpringJupiterTests__TestContext005_BeanFactoryRegistrations.java", "org/springframework/test/context/jdbc/EmptyDatabaseConfig__TestContext005_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext005_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext005_BeanDefinitions.java", // WebSpringJupiterTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext006_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext006_BeanDefinitions.java", @@ -437,14 +437,14 @@ class TestContextAotGeneratorIntegrationTests extends AbstractAotTests { "org/springframework/test/context/aot/samples/web/WebTestConfiguration__TestContext006_BeanDefinitions.java", "org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration__TestContext006_Autowiring.java", "org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration__TestContext006_BeanDefinitions.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext006_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext006_BeanDefinitions.java", // XmlSpringJupiterTests "org/springframework/context/event/DefaultEventListenerFactory__TestContext007_BeanDefinitions.java", "org/springframework/context/event/EventListenerMethodProcessor__TestContext007_BeanDefinitions.java", "org/springframework/test/context/aot/samples/common/DefaultMessageService__TestContext007_BeanDefinitions.java", "org/springframework/test/context/aot/samples/xml/XmlSpringJupiterTests__TestContext007_ApplicationContextInitializer.java", "org/springframework/test/context/aot/samples/xml/XmlSpringJupiterTests__TestContext007_BeanFactoryRegistrations.java", - "org/springframework/test/context/support/DynamicPropertySourceBeanInitializer__TestContext007_BeanDefinitions.java", + "org/springframework/test/context/support/DynamicPropertyRegistrarBeanInitializer__TestContext007_BeanDefinitions.java", }; }