기존에는 Mockito를 사용하여 mockist test 방식을 사용하여 테스트를 진행하였습니다.
그러나 IAS-Classicist-BDD-스타일로-테스트를-작성하자를 진행하면서 잦은 설계 변경에 대응하기 위해 Production Object를 사용한 Classicist 방식의 테스트로 전환하였고 더이상 기능 변경에 대해 stub를 수정할 필요가 없어졌습니다..
하지만, Classicist Test는 항상 Test를 위한 DB가 올라가 있어야 한다는 단점이 존재하기 때문에 비용적인 부담이 존재합니다.
그래서 Testcontainer를 적용하여 Test시에만 DB 컨테이너가 실행될수 있도록 설정하였습니다.
또한 저는 authentication server에서는 jpa를 board server에서는 mybatis를 사용하기 때문에 두가지 방식 모두 적용해보았습니다.
JPA는 굉장히 간단한 설정을 통해, test컨테이너를 사용할 수 있습니다.
먼저 testcontainer에 필요한 의존성을 설정해줍니다.
testImplementation "org.testcontainers:testcontainers:1.19.6"
testImplementation "org.testcontainers:junit-jupiter:1.19.6"
testImplementation "org.testcontainers:mysql:1.19.6"
다음으로는 application.properties의 설정을 변경합니다.
spring.datasource.url=jdbc:tc:mysql:8.0.0:///test
그런 다음 굉장히 쉽게 Test를 실행하면 Testcontainer를 사용할 수 있습니다.
(여기는 추가적으로 redis 컨테이너도 존재하지만, 일단 넘어가겠습니다.)
JPA의 경우에는 ddl-auto를 통해 JPA가 알아서 필요한 DB 테이블을 정의하고 db를 설정하며 사용하지만, MyBatis의 경우에는 직접 MySql container를 올려주고, 테이블을 정의하여야 합니다.
초기 설정으로는 위와 같이 의존성을 설정해줍니다..
CREATE TABLE IF NOT EXISTS board (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL
);
위와 같은 필요한 db 테이블을 정의하는 ddl 구문을(ddl-auto 설정에 따라) 작성하고 resource 폴더에 위치시킵니다.
public class WithContainerTest {
protected static MySQLContainer mySQLContainer = new MySQLContainer("mysql:latest")
.withDatabaseName("test")
.withUsername("test")
.withPassword("test");
static {
mySQLContainer.start();
System.setProperty("spring.datasource.url", mySQLContainer.getJdbcUrl());
System.setProperty("spring.datasource.username", mySQLContainer.getUsername());
System.setProperty("spring.datasource.password", mySQLContainer.getPassword());
Connection con;
try {
con = DriverManager.getConnection(
mySQLContainer.getJdbcUrl(),
mySQLContainer.getUsername(),
mySQLContainer.getPassword()
);
ScriptUtils.executeSqlScript(con, new ClassPathResource("createTable.sql"));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
다음과 같은 테스트 클래스를 작성합니다.
이 테스트 클래스의 static block은 클래스 초기화 블록으로 클래스가 처음 오딩될때 한번만 수행됩니다.
여기서는 사용할 Container를 정의하고 url, username, password를 가져옵니다. 다음으로 ScriptUtils.executeSqlScript 를 사용하여 사전에 정의한 ddl 구문을 실행시켜, table을 생성합니다.
테스트를 실행시켜 보면
JPA와 마찬가지로 mysql을 사용하여 테스트를 수행한 것을 확인 할 수 있습니다.
이렇게 JPA와 Mybatis 각각 다른환경에서 테스트 컨테이너를 적용해보고 다르게 적용하는 방법을 구현하여 봤습니다.
사실 제일 어려웠던 부분은 모든 테스트 중 단 한번만 실행되게 하는 부분이었는데, 잊고 있었던 static {}
로 정의되는 클래스 초기화 블럭을 사용하여 구현할 수 있었습니다.