테스트를 할 때 sql로 미리 데이터를 insert 하고 해당 데이터로 테스트를 진행하고 싶을 경우 다음과 같이 설정하면 된다.
먼저 테스트 폴더에 resources 폴더를 만들어서 applciation.yml (or properties)을 설정해준다.
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
storage-engine: innodb
hibernate:
ddl-auto: create-drop
show-sql: true
format_sql: true
defer-datasource-initialization: true
h2:
console:
enabled: true
테스트는 인메모리로 진행하는 게 좋기 때문에 따로 application.yml을 만들어 h2 database 설정을 해주었다. 자신이 사용하는 db에 맞게 설정하면 될 것 같다.
여기서 defer-datasource-initialization을 꼭 해주어야 sql script로 데이터를 로드할 수 있다.
설정을 다 해주었으면 resources 폴더 안에 sql script를 생성한 후, 테스트 데이터에 맞게 SQL을 작성한다.
그 후 테스트 코드에서 다음과 같이 설정해 준다.
@SpringBootTest
@Transactional
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class TakeClassTest {
...
@Autowired
DataSource dataSource;
@BeforeAll
public void init() {
try (Connection conn = dataSource.getConnection()) {
// 자신의 script path 넣어주면 됨
ScriptUtils.executeSqlScript(conn, new ClassPathResource("/db/h2/data.sql"));
} catch (Exception e) {
e.printStackTrace();
}
}
...
}
@BeforeAll 어노테이션은 최초 테스트 시작 전에 한 번 실행되기 때문에 본래 static method로 선언해야 하고, @Autowired로 주입받은 인스턴스를 사용하지 못한다. 주입받은 인스턴스를 사용하지 못하는 이유는 TestInstance의 Lifecycle이 기본값이 method이기 때문에 TakeClassTest의 인스턴스가 메서드 별로 다시 생성되어 다시 @Autowired 하기 때문이다.
@TestInstance 어노테이션을 사용해 TestInstance의 Lifecycle을 PER_CLASS로 바꿔줌으로 @BeforeAll을 static method로 선언하지 않고, 주입받은 인스턴스를 모든 메소드에서 공유 가능하도록 함으로써 DB에서 값을 가져와 메소드에서 공유해 사용할 수 있도록 해 주었다.
DB의 데이터를 공유해 사용하면 다음 테스트에서 오류가 발생할 수 있는데, 이를 방지하기 위해 @Transactional 어노테이션을 추가해 주었다. 테스트에서 @Transactional을 사용하면 기본값으로 Rollback이 true이기 때문에 한 테스트를 수행한 후에 데이터가 DB에 커밋되지 않고 롤백된다. 그렇기 때문에 각 메소드 별로 독립적으로 테스트를 수행할 수 있다.
TestInstance의 Lifecycle에 대해 이해가 잘 되지 않는다면 아래의 테스트 코드를 실행해보면 좋을 것 같다.
// @TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class InstanceTest {
int sum = 1;
@Test
void test1() {
sum += 2;
assertThat(sum).isEqualTo(3);
}
@Test
void test2() {
sum += 3;
assertThat(sum).isEqualTo(4);
}
}
위 코드대로 한 번 실행해본 후 @TestInstance의 주석을 풀고 테스트를 실행하면 어느 정도 감이 잡힌다.
참고
'Spring' 카테고리의 다른 글
Spring Validation 특정 String만 받도록 검증 하기 (0) | 2023.11.09 |
---|---|
Spring Boot & Thymeleaf 토이 프로젝트 [Course Registration System] (2) | 2022.04.01 |
[Spring][Error] Spring Security 적용할 때 circular reference, dependency가 cycle 형성하는 것 해결하기 (2) | 2022.03.14 |
AWS RDS(MariaDB)와 IntelliJ Database 연동하기 - [스프링 부트와 AWS로 혼자 구현하는 웹 서비스] (0) | 2022.03.05 |
SpringBoot 간단한 CRUD REST API 구현 및 JUnit5로 테스트하기 (0) | 2022.02.26 |
댓글