스프링 부트 3.2에서 docker-compose.yml와 연결하여 TestContainers를 설정하는 방법 (with Mysql)

2024. 7. 23. 14:53·Tech/Spring

 

개요

로컬 혹은 CI 서버에서 실제 운영 환경과 같은 디비를 사용하여 통합 테스트를 하고 싶어 TestContainers 설정을 적용했다.

세부 설정은 docker-compose.yml로 관리하는게 편하여 이를 import하는 방식으로 구현했다.

 

환경

스프링 부트 3.2.6

Gradle 8.8

자바 17

 

설정

gradle에 라이브러리 추가

ext {
    testcontainersVersion = "1.19.0"
}

dependencies {
    testImplementation "org.springframework.boot:spring-boot-testcontainers"
    testImplementation 'org.testcontainers:mysql'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

dependencyManagement {
    imports {
        mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}"
    }
}

 

 

src/test/resources
ㄴ application-test.yml
ㄴ docker-compse.yml
ㄴ schema.sql

 

docker-compose.yml

version: "3.8"

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: container
      MYSQL_CHARSET: utf8mb4
      MYSQL_COLLATION: utf8mb4_unicode_ci
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 3306
    volumes:
      - ./schema.sql:/docker-entrypoint-initdb.d/schema.sql
    networks:
      - test_network

networks:
  test_network:
    driver: bridge
    name: test_network
  • 레디스 등 다른 서비스를 띄워야 한다면 일반적인 docker-compose.yml 하는 것처럼 추가하면 된다.
  • DB에 DDL을 실행시키기 위해 docker volumes 설정
  • 네트워크를 지정하지 않으면 TestContainer를 가동시킬때마다 네트워크를 별도로 생성하게 된다.
    • 네트워크 풀이 가득찰 경우 아래와 같은 에러가 발생하여 실행이 안될수도 있으니 네트워크를 별도로 지정해주자!

14:02:57.541 [Test worker] ERROR tc.docker:24.0.2 -- Log output from the failed container: Network epceaxzqtavu_default Creating Network epceaxzqtavu_default Error failed to create network epceaxzqtavu_default: Error response from daemon: all predefined address pools have been fully subnetted

 

  • name 까지 지정해줘야 한다. 지정해 주지 않으면 rhp9z3rirgm1_test_network 처럼 앞에 랜덤 접두사가 붙은 네트워크가 실행시 마다 종종 추가된다.

 

schema.sql

DROP TABLE IF EXISTS table_name;

CREATE TABLE `table_name` {}

 

  • 필요한 DDL을 넣어 주자

 

 

IntegrationTest.java

@ActiveProfiles("test")
@SpringBootTest
@ContextConfiguration(initializers = IntegrationTest.IntegrationTestInitializer.class)
public class IntegrationTest {

    private static final ComposeContainer DOCKER_COMPOSE =
        new ComposeContainer(new File("src/test/resources/docker-compose.yml"))
            .withExposedService("mysql", 3306, Wait.forLogMessage(".*mysqld: ready for connections.*", 2));

    @BeforeAll
    public static void setupContainers() {
        DOCKER_COMPOSE.start();
    }

    static class IntegrationTestInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

        @Override
        public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {
            Map<String, String> properties = new HashMap<>();

            setDatabaseProperties(properties);

            TestPropertyValues.of(properties).applyTo(applicationContext);
        }

        private void setDatabaseProperties(Map<String, String> properties) {
            String rdbmsHost = DOCKER_COMPOSE.getServiceHost("mysql", 3306);
            Integer rdbmsPort = DOCKER_COMPOSE.getServicePort("mysql", 3306);
            properties.put("spring.datasource.url", "jdbc:mysql://" + rdbmsHost + ":" + rdbmsPort + "/container");
            properties.put("spring.datasource.username", "root");
            properties.put("spring.datasource.password", "password");
        }

    }
}

 

  • docker-compose.yml 가져오고 스프링 컨텍스트를 띄우기 전에 디비 설정 해준다음, TestContainers를 실행

 

    private static final ComposeContainer DOCKER_COMPOSE =
        new ComposeContainer(new File("src/test/resources/docker-compose.yml"))
            .withExposedService("mysql", 3306, Wait.forLogMessage(".*mysqld: ready for connections.*", 2));

 

  • 위 코드가 핵심이다. 처음에 DockerComposeContainer으로 했다가 에러가 떠서 ComposeContainer으로 변경했다. 내부 코드 까보니 DockerComposeContainers는 @Deprecated 되었다.
  • 컨테이너가 뜬 다음 테스트 코드가 실행 되야 하기 때문에 Wait을 설정해줘야 한다. 안그럼 실행을 할 수 없다. mysql 메시지 내용 찾느라 조금 헤멤..
  • 다른 서비스도 띄워야 한다면 .withExposedService 한줄 추가하고 IntegrationTestInitializer에서 해당 서비스 설정을 추가하면 된다.

 

public class DatabaseTests extends IntegrationTest {

    @Autowired
    private TestJpaRepository testJpaRepository;

    @Test
    void test() {
        TestEntity save = testJpaRepository.save(TestEntity.create(1L));
    }

}

 

  • 생성한 DDL에 맞는 엔티티 하나를 가지고 간단히 삽입 테스트를 했을때 에러가 뜨지 않으면 성공

 

 

추후 레디스 같은 다른 서비스도 추가하게 되면 글 내용을 수정하겠다!!

 

 

 

 

참고

https://java.testcontainers.org/modules/docker_compose/#compose-v2

https://danielme.com/2023/04/13/testing-spring-boot-docker-with-testcontainers-and-junit-5-mysql-and-other-images/

https://velog.io/@byulcode/Docker-compose%EB%A1%9C-Mysql-%EC%84%A4%EC%A0%95

 

https://jaehoney.tistory.com/222

 

↓↓↓ 아래 글이 많은 도움이 되었다. Shout out to dkswnkk..

https://dkswnkk.tistory.com/719

 

TestContainer로 통합 테스트 환경 구축하기

[개요] 통합 테스트 환경을 구축할 때, 데이터베이스와의 연동은 주요한 고려사항 중 하나이며, 테스트의 안정성과 신뢰성을 높이기 위해서는 실제 운영 환경과 유사한 데이터베이스 환경에서

dkswnkk.tistory.com

 

 

저작자표시 (새창열림)

'Tech > Spring' 카테고리의 다른 글

kotlin internal class  (0) 2025.10.19
SpringBoot 커스텀 프로퍼티에 대한 문서와 자동완성 ※ Spring Configuration Processor  (1) 2024.04.17
2개 이상의 DB를 사용하는 Spring Boot 환경에서 Spring Data Jpa 사용시 트랜잭션 관련 에러  (1) 2023.01.29
요청으로 들어온 language 값에 따른 GlobalExceptioner에서 다국어 처리 (i18n, yml) + spring validaiton 다국어처리  (1) 2022.05.23
Validation 클래스 단위 제약과 조건부 검사 설정  (0) 2021.12.22
'Tech/Spring' 카테고리의 다른 글
  • kotlin internal class
  • SpringBoot 커스텀 프로퍼티에 대한 문서와 자동완성 ※ Spring Configuration Processor
  • 2개 이상의 DB를 사용하는 Spring Boot 환경에서 Spring Data Jpa 사용시 트랜잭션 관련 에러
  • 요청으로 들어온 language 값에 따른 GlobalExceptioner에서 다국어 처리 (i18n, yml) + spring validaiton 다국어처리
소프
소프
  • 소프
    기회는 찬스
    소프
  • 전체
    오늘
    어제
    • 분류 전체보기 (138) N
      • Language (20)
        • Java (19)
        • Design Pattern (1)
      • Tech (27)
        • Spring (19)
        • JPA (3)
        • QueryDSL (1)
        • Gradle (4)
      • 개발 생각 (1)
      • IT Book (0)
        • 자바_스프링 개발자를 위한 실용주의 프로그래밍 (0)
      • Database (4)
        • Mysql (4)
        • Redis (0)
      • 네트워크 (1)
      • 운영체제 (2)
      • IDE (12)
        • Intellij (9)
        • vscode (2)
        • datagrip (1)
      • 인프라 (11)
        • Docker (2)
        • Jenkins (7)
        • Github Actions (1)
        • GCP (1)
      • 형상관리 (2)
        • gitlab (2)
        • git (0)
      • 외부활동 (44)
        • CS 면접 끝장내기 - 데이터베이스 1기 (5)
        • CS 면접 끝장내기 - 컴퓨터 네트워크 2기 (5)
        • CS 면접 끝장내기 - 자바 2기 (0)
        • TDD, 클린 코드 with Java 17기 (7)
        • ATDD, 클린 코드 with Spring 8기 (6)
        • 루퍼스 2기 (21)
      • 프로젝트 (0)
      • 회고 (6)
      • 기타 (1)
        • 제미니의 개발 실무 (0)
  • 블로그 메뉴

    • 홈
    • Github
    • LinkedIn
    • 방명록
  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.6
소프
스프링 부트 3.2에서 docker-compose.yml와 연결하여 TestContainers를 설정하는 방법 (with Mysql)
상단으로

티스토리툴바