SpringBoot 테스트를 위한 DB 격리

iseon_u·2023년 5월 10일
0

TDD

목록 보기
1/3
post-thumbnail

SpringBoot 테스트를 위한 DB 격리


DB 격리를 생각하게 된 계기

  • 단위 테스트만 작성할 땐 @Transactional 어노테이션으로 DB 롤백이 가능 ✅
  • @SpringBootTest에서 RANDOM_PORTDEFINED_PORT 를 사용하는 테스트에서는 적용 불가 ❌

@SpringBootTest RANDOM_PORT, DEFINED_PORT 에서 @Transacation 롤백이 안되는 이유

  • RANDOM_PORT, DEFINED_PORT를 사용하면 별도의 쓰레드에서 스프링 컨테이너가 실행 된다.
  • 때문에 테스트와 별개의 쓰레드에서 스프링 컨테이너가 실행 되므로 하나의 트랜잭션으로 묶일 수가 없다.

해결 방법

  1. 테스트를 위한 DB 환경 구축
  2. 테스트 격리를 위한 모든 테이블 데이터 초기화
    1. @AfterEach 를 사용해 DB 삭제 메서드 작성
    2. @Sql어노테이션을 통한 DB 초기화
    3. Spring Batch를 사용하여 DB 초기화

테스트를 위한 DB 환경 구축

test/resources/application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/one_delivery_test?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
spring.datasource.username=root
  • application.properties를 따로 작성
  • 테스트용 DB 생성

@Sql 어노테이션을 통한 DB 초기화

/resources/sql/truncate.sql

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE cart
TRUNCATE TABLE menu
TRUNCATE TABLE store
...
SET FOREIGN_KEY_CHECKS = 1;
@Sql(scripts = {"/sql/truncate.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  • @Sql 어노테이션을 통해 테스트 사용에 따라 이전 또는 이후에 DB 초기화 실행

DB 초기화 SQL

  1. 모든 테이블에 대한 TRUNCATE TABLE 명령어 리스트 추출
SELECT CONCAT('TRUNCATE TABLE ', TABLE_NAME, ';') AS list FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'one_delivery_test'
  1. 제약 조건 무효화
SET FOREIGN_KEY_CHECKS = 0;
  1. 모든 테이블에 대한 TRUNCATE TABLE 명령어 실행
  2. 제약 조건 재설정
SET FOREIGN_KEY_CHECKS = 1;

Spring Batch를 사용하여 DB 초기화

test/resources/application.properties

spring.batch.jdbc.initialize-schema=always
profile
🧑🏻‍💻 Hello World!

0개의 댓글