Testcontainers를 사용한 테스트 환경 분리하기

January 07, 2024


Why we need Testcontainers?

테스트를 위해서는 실제 database가 아닌 환경에서 수행할 필요가 있습니다.

H2를 써도 되지만, 특정 rdb에 특화된 기능을 사용하기 어려운 경우도 있습니다.

대안으로 docker compose로 테스트하기 위한 DB를 같이 띄워도 되지만, 이 역시 관리의 대상이 됩니다.

대신 Testcontainers를 사용하면, 간단하게 외부와 격리된 테스트 환경을 구성할 수 있습니다.

적용법

build.gradle에 아래의 테스트 의존성을 추가합니다.

MySQL을 사용하는 예시

testImplementation "org.testcontainers:testcontainers:1.19.7"
testImplementation "org.testcontainers:junit-jupiter:1.19.7"
testImplementation "org.testcontainers:jdbc:1.19.7"
testImplementation "org.testcontainers:mysql:1.19.7"

테스트용 Redis 추가

  • Redis를 사용하기 위해선 아래의 TestRedisConfig 클래스를 추가합니다.
@TestConfiguration
public class TestRedisConfig {
    private static final String REDIS_DOCKER_IMAGE = "redis:7.2.0-alpine";

    public TestRedisConfig(RedisProperties redisProperties) {

        GenericContainer<?> redisContainer = new GenericContainer<>(DockerImageName.parse(REDIS_DOCKER_IMAGE))
                .withExposedPorts(redisProperties.getPort())
                .withReuse(true);

        redisContainer.start();
        redisProperties.setHost(redisContainer.getHost());
        redisProperties.setPort(redisContainer.getFirstMappedPort());
    }
}

application-test.yml 작성

  • src/test/resources/application-test.yml에는 아래와 같이 원하는 MySQL 버전과 Testcontainers 설정을 합니다.
spring.config.activate.on-profile: test # test 프로필에서만 사용하도록 합니다.
spring:
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true
    open-in-view: false
    defer-datasource-initialization: true

  datasource:
    driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
    url: jdbc:tc:mysql:8.0.36://test # 원하는 버전 설정

  data:
    redis:
      host: localhost
      port: 6379
      password: # 공백이어야 합니다.

실제 사용

  • DataJpaTest에서 MySQL, Redis 테스트 컨테이너를 사용할 수 있습니다.
@ActiveProfiles("test")
@DataJpaTest
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // H2 사용 금지
@Import({RedisProperties.class, TestRedisConfig.class})
class MyRepositoryTest {
    @Autowired
    private SomeEntityRepository someEntityRepository;
}

Profile picture

이재원

이해하기 쉬운 코드를 작성하려 고민합니다.


© 2024 Won's blog Built with Gatsby