Redis Testcontainer with Kotlin and Spring Boot

I found lots of samples for creating a redis testcontainer in Spring Boot tests. But none of them really worked. Below is a working base class with a sample. It is based on Spring Boot 3.1.2 and latest testcontainer version at time of writing (“org.testcontainers:testcontainers:1.18.3”). The testcontainer-redis versions were avoided on purpose because they were only available with quite old testcontainer version.

import org.junit.jupiter.api.BeforeAll
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
abstract class RedisTest {
    companion object {
        private const val REDIS_IMAGE = "redis:7-alpine"
        private const val REDIS_PORT = 6379

        private const val REDIS_CONFIG_HOST = "spring.data.redis.host"
        private const val REDIS_CONFIG_PORT = "spring.data.redis.port"

        private val redisContainer = GenericContainer<Nothing>(REDIS_IMAGE).apply {
            withExposedPorts(REDIS_PORT)
            withReuse(true)
        }

        @JvmStatic
        @BeforeAll
        fun beforeAll() {
            if (!redisContainer.isRunning) {
                redisContainer.start()
                redisContainer.setWaitStrategy(HostPortWaitStrategy())
            }
        }

        @JvmStatic
        @DynamicPropertySource
        fun properties(registry: DynamicPropertyRegistry) {
            registry.add(
                REDIS_CONFIG_HOST,
                redisContainer::getContainerIpAddress
            )
            registry.add(
                REDIS_CONFIG_PORT,
                redisContainer::getFirstMappedPort
            )
        }
    }
}

With this in place you can create a simple test by extending RedisTest

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.core.RedisTemplate

class EventSourceTest @Autowired constructor(
    val redisTemplate: RedisTemplate<String, String>
) : RedisTest() {

    @ParameterizedTest
    @CsvSource(
        value = [
            "test1, 1",
            "test2, 2",
            "test3, 3",
        ]
    )
    fun redis(
        key: String,
        value: String
    ) {
        redisTemplate.opsForValue().set(
            key,
            value
        )
        assertThat(redisTemplate.opsForValue().getAndDelete(key)).isEqualTo(value)
    }

}