001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.test.context;
018
019import java.lang.annotation.Documented;
020import java.lang.annotation.ElementType;
021import java.lang.annotation.Retention;
022import java.lang.annotation.RetentionPolicy;
023import java.lang.annotation.Target;
024
025/**
026 * Method-level annotation for integration tests that need to add properties with
027 * dynamic values to the {@code Environment}'s set of {@code PropertySources}.
028 *
029 * <p>This annotation and its supporting infrastructure were originally designed
030 * to allow properties from
031 * <a href="https://www.testcontainers.org/">Testcontainers</a> based tests to be
032 * exposed easily to Spring integration tests. However, this feature may also be
033 * used with any form of external resource whose lifecycle is maintained outside
034 * the test's {@code ApplicationContext}.
035 *
036 * <p>Methods annotated with {@code @DynamicPropertySource} must be {@code static}
037 * and must have a single {@link DynamicPropertyRegistry} argument which is used
038 * to add <em>name-value</em> pairs to the {@code Environment}'s set of
039 * {@code PropertySources}. Values are dynamic and provided via a
040 * {@link java.util.function.Supplier} which is only invoked when the property
041 * is resolved. Typically, method references are used to supply values, as in the
042 * following example.
043 *
044 * <h3>Precedence</h3>
045 * <p>Dynamic properties have higher precedence than those loaded from
046 * {@link TestPropertySource @TestPropertySource}, the operating system's
047 * environment, Java system properties, or property sources added by the
048 * application declaratively by using
049 * {@link org.springframework.context.annotation.PropertySource @PropertySource}
050 * or programmatically. Thus, dynamic properties can be used to selectively
051 * override properties loaded via {@code @TestPropertySource}, system property
052 * sources, and application property sources.
053 *
054 * <h3>Example</h3>
055 * <pre class="code">
056 * &#064;SpringJUnitConfig(...)
057 * &#064;Testcontainers
058 * class ExampleIntegrationTests {
059 *
060 *     &#064;Container
061 *     static RedisContainer redis = new RedisContainer();
062 *
063 *     // ...
064 *
065 *     &#064;DynamicPropertySource
066 *     static void redisProperties(DynamicPropertyRegistry registry) {
067 *         registry.add("redis.host", redis::getContainerIpAddress);
068 *         registry.add("redis.port", redis::getMappedPort);
069 *     }
070 *
071 * }</pre>
072 *
073 * @author Phillip Webb
074 * @author Sam Brannen
075 * @since 5.2.5
076 * @see DynamicPropertyRegistry
077 * @see ContextConfiguration
078 * @see TestPropertySource
079 * @see org.springframework.core.env.PropertySource
080 */
081@Target(ElementType.METHOD)
082@Retention(RetentionPolicy.RUNTIME)
083@Documented
084public @interface DynamicPropertySource {
085}