Как правило, когда вы используете в Spring Framework тестах какие-то специфичные properties, у вас есть несколько вариантов чтобы задать их значения:

application.properties

вы можете использовать файл application.properties в тестовых ресурсах, тогда эти настройки будут применены ко всем тестовым сценариям, которые вы пишите:

sprint.redis.host = 127.0.0.1
spring.redis.port = 15092

TestPropertySource

можно указать значение свойств прямо в тест-кейсе при помощи аннотации @TestPropertiesSource, которая делает inline значения, указаного в ней:

@SpringBootTest
@ExtendWith(SpringExtension.class)
@TestPropertySource(properties = "spring.redis.host=127.0.0.1")
class SomeRedisTest {

    ...
}

Проблема

А что делать, если значение, которое вам нужно задать - не константа?

В нашем примере выше хост и порт, на котором стартует redis, могут быть нам не известны до того как мы запустим тест. В такой ситуации легко оказаться, если вы используете TestContainers для запуска redis в тестах. До того как будет запущен контейнер, вы не сможете указать порт для теста. Таким образом, вариант использования application.properties отпадает автоматически, как и аннотация @TestPropertySource, потому что в java-аннотации можно указать только константное значение.

Из-за таких особенностей приходится создавать в тестах свои ApplicationContextInitializer-ы или инициализировать эти свойства в static инициализаторах:

@Testcontainers
@ContextConfiguration(initializers = RedisIntegrationTest.CustomInitializer.class)
@DataRedisTest
public class RedisIntegrationTest {

    @Container
    public static RedisContainer redis = new RedisContainer();

    static class CustomInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        @Override
        public void initialize(
                ConfigurableApplicationContext configurableApplicationContext) {
            TestPropertyValues.of("spring.redis.port=" + redis.getMappedPort())
                    .applyTo(configurableApplicationContext.getEnvironment());
        }

    }
}

Аннотация @Testcontainers работает при помощи расширения для junit5, которое ищет контейнеры (помеченные аннотацией @Container) в коде теста и запускает их.

Конечно, можно было сделать решение, заточенное специально для этой задачи, и добавить какое-нибудь расширение, стартующее redis-контейнер и проставляющее host/port, на котором он запустился, перед запуском теста. Честно говоря, я так и сделал, когда первый раз столкнулся с этой задачей, пару месяцев назад (что из этого получилось можно посмотреть тут: github.com/jupiter-tools/spring-test-redis), но ведь можно сделать что-то более универсальное.

Решение

В результате у меня получилось сделать механизм, позволяющий пометить аннотацией @DynamicTestProperty метод, добавляющий новые значения переменных окружения для теста:

@SpringBootTest
@Testcontainers
@ExtendWith(SpringExtension.class)
class RedisTestcontainersTest {

    private static final Integer REDIS_PORT = 6379;

    @Container  (1)
    private static GenericContainer redis = new GenericContainer("redis:latest")
            .withExposedPorts(REDIS_PORT);

    @DynamicTestProperty   (2)
    private static TestPropertyValues props() {
        return TestPropertyValues.of("spring.redis.host=" + redis.getContainerIpAddress(),
                                     "spring.redis.port=" + redis.getMappedPort(REDIS_PORT));
    }

    @Autowired
    private RedisTemplate redisTemplate;  (3)

    @Test
    void readWriteValueByRedisTemplate() {
        String key = "test";
        String value = "sabracadabra";
        // Act
        redisTemplate.opsForValue().set(key, value);
        // Assert
        assertThat(redisTemplate.opsForValue().get(key)).isEqualTo(value);
    }
}
1 объявляем контейнер для redis
2 прописываем хост/порт, на котором стартовал контейнер в стандартные спринговые настройки
3 используем в тесте redis, запущенный в тест-контейнере

И чтобы все это работало в ваших spring-boot проектах, нужна всего лишь одна зависимость:

<dependency>
    <groupId>com.jupiter-tools</groupId>
    <artifactId>spring-dynamic-property</artifactId>
    <version>0.1</version>
</dependency>

GitHub репозиторий

Больше подробностей вы можете прочитать на странице проекта.

Не стесняйтесь ставить звездочки на гитхабе =)