Spring DB 테스트

조승빈·2024년 11월 13일

Spring DB

목록 보기
2/8

Spring Boot 테스트의 기본 개념

@SpringBootTest: @SpringBootTest는 Spring Boot 애플리케이션 컨텍스트를 로드하여 통합 테스트를 수행할 수 있도록 도와주는 애노테이션이다. @SpringBootApplication으로 설정된 메인 클래스를 자동으로 찾아 사용한다.

테스트 전용 데이터베이스 운영의 필요성

로컬 환경과 동일한 데이터베이스를 테스트에서 사용하면 데이터가 덮어쓰이거나 변경될 위험이 있어 테스트 결과에 영향을 줄 수 있다. 테스트 환경에서는 테스트 전용 데이터베이스를 사용하는 것이 좋다.

테스트의 중요한 원칙

1. 테스트 간 격리

각 테스트는 서로의 결과에 영향을 주지 않아야 하며, 다른 테스트와 완전히 독립적으로 실행될 수 있어야 한다.
이를 통해, 테스트 간의 의존성이나 부작용을 방지할 수 있다.

2. 테스트의 반복 실행 가능성

테스트는 반복해서 실행할 수 있어야 하며, 테스트 실행 시 초기 상태로 돌아가야 한다.
예를 들어, 테스트 실행 중 데이터가 추가되거나 변경되었다면 다음 테스트 실행 시 영향을 미칠 수 있으므로 이를 방지해야 한다.

@Transactional

@Transactional 애노테이션을 테스트에 사용하면, 기본적으로 테스트 완료 후 트랜잭션을 자동으로 롤백한다.
이 방식은 테스트 중간에 예외가 발생해도 커밋되지 않은 상태로 트랜잭션이 종료되어 데이터베이스에 변경사항이 반영되지 않게 된다.

@BeforeEach@AfterEach를 사용한 트랜잭션 관리

@BeforeEach@AfterEach: Spring Boot는 각 테스트 메서드 전에 @BeforeEach 메서드를, 후에 @AfterEach 메서드를 실행할 수 있다.

각 테스트 전에 필요한 초기화 작업을 수행하고, 테스트가 끝난 후에는 정리 작업을 할 수 있어 테스트 환경을 일정하게 유지할 수 있다.

예시 코드

@SpringBootTest
@Transactional  // 자동으로 롤백 처리
public class MyRepositoryTest {

    @Autowired
    private MyRepository myRepository;

    @BeforeEach
    public void setUp() {
        // 각 테스트 전에 실행될 초기화 코드 작성
    }

    @AfterEach
    public void tearDown() {
        // 각 테스트 후에 실행될 정리 작업 작성
    }

    @Test
    public void testInsertAndRollback() {
        // 테스트 코드 작성
        myRepository.save(new Entity(...));
        // 트랜잭션 롤백으로 인해 테스트 종료 시 데이터베이스에 반영되지 않음
    }
}

@Transactional이 없는 경우 데이터 정리 방법:

@Transactional을 사용하지 않을 경우에는 @AfterEach를 이용해 수동으로 데이터를 정리해야 한다.

테스트 전용 데이터베이스 설정 방법

application-test.yml 또는 application-test.properties와 같은 테스트 전용 프로파일 파일을 설정하여 테스트 환경에서는 별도의 데이터베이스가 사용되도록 구성할 수 있다.

@Transactional의 동작 과정

  1. set autocommit false: 트랜잭션이 시작되며, 자동 커밋이 비활성화
  2. INSERT SQL 실행: 데이터베이스에 데이터를 삽입하는 테스트가 실행
  3. SELECT SQL 실행: 데이터 조회 등 필요한 작업이 진행
  4. 아이템 반환: 작업 결과가 반환
  5. 롤백: 테스트 종료 시 트랜잭션을 커밋하지 않고 롤백
  6. 아이템 제거: 롤백되므로, 테스트에서 추가한 데이터는 데이터베이스에 반영되지 않음

트랜잭션의 테스트 참여

  • 테스트 메서드에 @Transactional이 선언되어 있으면, 해당 트랜잭션 내에서 실행되는 모든 코드가 동일한 트랜잭션에 참여한다.
  • 리포지토리 클래스나 서비스에 정의된 @Transactional 애노테이션 역시 테스트에서 시작된 트랜잭션에 참여하게 되어 하나의 트랜잭션에서 모든 작업이 처리된다.
  • 이 과정에서 같은 트랜잭션을 사용한다는 것은 동일한 데이터베이스 커넥션을 공유한다는 의미도 포함된다.

테스트 종료 시 자동 롤백

테스트가 중간에 예외로 인해 강제로 종료되더라도, 트랜잭션이 커밋되지 않으므로 자동으로 롤백된다.
트랜잭션이 롤백되므로, 테스트 도중에 발생한 모든 데이터 변경은 데이터베이스에 반영되지 않는다.

@Commit과 @Rollback(false)

@Commit: 트랜잭션을 강제로 커밋하고 싶을 때 사용한다. 테스트 트랜잭션이 종료될 때 롤백 대신 커밋되어 데이터베이스에 반영된다.
@Rollback(false): 테스트 종료 시 롤백을 비활성화하려면 이 애노테이션을 사용한다. 이 경우 테스트가 끝나도 데이터가 유지된다.

임베디드 모드 데이터베이스

테스트 환경에서 별도의 데이터베이스를 세팅하는 것은 번거롭기 때문에 임베디드 데이터베이스를 사용하는 것이 일반적이다.

예를 들어, H2 데이터베이스는 JVM 메모리 내에서 데이터베이스를 실행할 수 있는 기능을 제공하여, 테스트 시 독립적인 데이터베이스 환경을 쉽게 구축할 수 있다.
H2를 임베디드 모드로 실행하면 테스트가 끝날 때 데이터베이스가 초기화되므로 테스트 데이터가 남지 않으며 반복 실행이 용이하다.

데이터베이스 초기화 설정 방법

메모리 데이터베이스는 애플리케이션이 종료될 때 함께 사라지기 때문에 애플리케이션 실행 시점에 데이터베이스 테이블을 새로 만들어주어야 한다. 스프링부트는 sql 스크립트를 실행해서 애플리케이션 로딩 시점에 데이터베이스를 초기화하는 기능을 제공한다.

/src/test/resources/schema.sql 파일을 생성하여 테이블 구조를 정의할 수 있다.

schema.sql 파일은 데이터베이스 스키마를 정의하는 SQL 문들을 포함한다. 이 파일에 작성된 스키마는 애플리케이션이 로딩될 때 실행되어 필요한 테이블 구조가 생성된다.

주석 처리 시 임베디드 데이터베이스 자동 연결

Spring Boot에서 테스트 환경의 application.yml 파일에서 spring.datasource.urlspring.datasource.username을 주석 처리하면, Spring Boot가 자동으로 임베디드 모드의 데이터베이스에 연결하는 DataSource를 생성하여 사용하게 된다.

  1. spring.datasource.url, spring.datasource.username과 같은 설정을 명시하지 않으면, Spring BootH2, HSQL, Derby와 같은 임베디드 데이터베이스가 의존성에 포함되어 있는지 확인한다.
  2. 임베디드 데이터베이스가 존재하면 자동으로 임베디드 데이터베이스용 DataSource를 생성하여 연결 한다.
    이 경우, 임베디드 데이터베이스가 애플리케이션 메모리 내에서 실행되므로 별도의 데이터베이스 설정 없이도 테스트를 독립적으로 수행할 수 있다.
profile
평범

0개의 댓글