testcontainer 사용 방법

greenTea·2023년 12월 4일
0

Testcontainers란? 🤔

Testcontainers는 Docker 컨테이너를 사용하여 테스트 환경을 동적으로 생성하고 관리할 수 있는 Java 라이브러리입니다. 이를 사용하면 데이터베이스, 메시지 큐, 웹 서버 등 다양한 서비스를 테스트에 쉽게 통합할 수 있습니다.
코드를 보시면 더욱 이해하기가 쉽습니다.

Testcontainers 설치하기

먼저, 프로젝트의 build.gradle 파일에 Testcontainers 의존성을 추가해야 합니다

testImplementation 'org.testcontainers:testcontainers:1.19.3'
testImplementation 'org.testcontainers:junit-jupiter:1.19.3'

이 의존성을 추가함으로써, Testcontainers 라이브러리를 테스트 코드에서 사용할 수 있게 됩니다.

컨테이너 설정하기 🚀

Testcontainers를 사용한다면 원하는 컨테이너를 테스트를 실행하면서 실시간으로 띄웠다가 내릴수 있습니다.

여기서는 redis를 기준으로 작성해보겠습니다.

@Testcontainers
public class RedisContainerTest {

    @Container
    private GenericContainer redisContainer = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine"))
            .withExposedPorts(6379);
    ...
}

이 코드에서 @Container 어노테이션은 Testcontainers가 해당 필드에 Docker 컨테이너를 실행하도록 지시합니다.
@Container어노테이션을 달아줌으로써 컨테이너의 시작과 종료를 저희가 직접 호출 하지 않고 테스트의 생명주기와 같이 돌 수 있도록 해줄 수 있습니다.(원래라면 start,stop등으로 종료를 해줘야 합니다.)

  1. DockerImageName.parse("redis:5.0.3-alpine")를 이용하여 어떤 도커 이미지를 띄울 것인지를 정의하고 있습니다. 그냥 string으로 넣어주셔도 됩니다.
  2. withExposedPorts(6379)를 통해 내부의 6379랑 연결시켜주었습니다. 외부(호스트)의 포트는 랜덤으로 연결되고 이때 랜덤 포트를 내부 컨테이너의 6379와 연결시켜주는 작업입니다.

추가 설정 옵션 🛠️

GenericContainer 클래스는 다양한 설정 옵션을 제공합니다:

  • 환경 변수 설정: .withEnv("REDIS_PASSWORD", "yourpassword")를 사용하여 컨테이너에 환경 변수를 설정할 수 있습니다.
  • 커맨드 지정: .withCommand("redis-server", "--appendonly", "yes")를 사용하여 컨테이너 시작 시 실행할 명령어를 지정할 수 있습니다.
  • 볼륨 마운트: .withFileSystemBind("/local/path", "/container/path")를 사용하여 호스트와 컨테이너 간 파일 시스템을 마운트할 수 있습니다.

코드 전체 보기

@Testcontainers
public class MyTest {

	@Container
	private GenericContainer redisContainer = new GenericContainer(DockerImageName.parse("redis:5.0.3-alpine"))
		.withExposedPorts(6379);

	private RedisTemplate<String, Object> redisTemplate;

	@BeforeEach
	void setUp() {
		// RedisTemplate 설정
		String redisHost = redisContainer.getHost();
		Integer redisPort = redisContainer.getFirstMappedPort();

		RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration(redisHost, redisPort);
		LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisConfig);
		lettuceConnectionFactory.afterPropertiesSet();

		redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(lettuceConnectionFactory);
		redisTemplate.afterPropertiesSet();
	}

	@Test
	void test1() {

		redisTemplate.opsForValue().set("yohan","hello");

		String yohan = (String)redisTemplate.opsForValue().get("yohan");

		Assertions.assertEquals(yohan,"hello");

	}
}

위에서는 redisTemplate을 이용하였습니다.
@BeforeEach를 보면 redisContainer.getHost()redisContainer.getFirstMappedPort()가 보이는데 해당 메소드들을 통해 연결된 host와 port를 가져올 수 있습니다.
이를 통해 testcontainer로 띄운 redis의 설정 값을 가져와 test에 연결할 수 있습니다.

redis와 관련한 작업을 redisTemplate을 이용하여 처리하였습니다.

위의 방식외에도 RedisClientStatefulRedisConnection을 이용하는 방식도 있습니다.

다른 방식

GenericContainer의 경우 범용적으로 사용하는 방식이라면 testconatiner가 전용으로 지원해주는 container들도 존재합니다.
아래는 mysql과 관련한 코드입니다.

@Testcontainers
public class MySQLContainerTest {

    @Container
    private MySQLContainer mysqlContainer = new MySQLContainer(DockerImageName.parse("mysql:8.0.26"))
            .withDatabaseName("testdb")
            .withUsername("user")
            .withPassword("password");

    @BeforeEach
    void setUp() {
        // MySQL 설정
        String jdbcUrl = mysqlContainer.getJdbcUrl();
        String username = mysqlContainer.getUsername();
        String password = mysqlContainer.getPassword();
        //연결 작업 수행
    }
}

mysqlContainer를 이용한다면 이름, 비밀번호 등을 더욱 쉽게 설정 할 수 있습니다.

마치며 🎉

Testcontainers를 사용하면 테스트 환경을 빠르고 쉽게 구성할 수 있으며, 이를 통해 테스트의 신뢰성과 일관성을 크게 향상시킬 수 있습니다.

profile
greenTea입니다.

0개의 댓글