[Spring Boot] @SpringBootTest 통합 테스트와 @Transactional

Lundy·2023년 4월 11일
0

Spring Boot

목록 보기
3/6
post-thumbnail

여태 해왔던 기능 검증을 위한 단위 테스트와 유사하지만,

실제 운영 환경에서 사용될 클래스들을 통합하여 테스트해주는 @SpringBootTest 어노테이션에 대해 알아보자.

1. @SpringBootTest

@SpringBootTest는 스프링 컨테이너와 DB까지 연결하여 통합 테스트를 할 수 있게 하는 어노테이션이다.

앞서 언급했듯이 실제 운영 환경에서 사용될 클래스들을 통합하여 테스트할 수 있다.


2. @Transactional

테스트 케이스에 @Transactional이 붙으면 테스트 시작 전에 트랜잭션을 시작하고 완료 후에는 롤백하게 된다.

@Transactional 어노테이션을 사용하면 DB에 데이터가 남지 않아 다음 테스트에 영향을 주지 않는다.

이는 단위 테스트의 @BeforeEach, @AfterEach 어노테이션과 유사한 기능을 한다.


3. 단위 테스트와 통합 테스트이 비교 예시

  • 단위 테스트
package hello.hellospring.service;
 
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
 
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
 
public class MemberServiceTest {
 
    MemberService memberService;
    MemoryMemberRepository memberRepository;
	
    // 테스트의 독립성을 위해 @BeforeEach와 @AfterEach를 사용하여 repository를 삭제, 재생성해줌
    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
 
    @AfterEach
    public void afterEach() {
        memberRepository.clearStore();
    }
 
    @Test
    public void 회원가입() throws Exception {
        //Given
        Member member = new Member();
        member.setName("hello");
        //When
        Long saveId = memberService.join(member);
        //Then
        Member findMember = memberRepository.findById(saveId).get();
        assertEquals(member.getName(), findMember.getName());
    }
 
    @Test
    public void 중복_회원_예외() throws Exception {
        //Given
        Member member1 = new Member();
        member1.setName("spring");
        Member member2 = new Member();
        member2.setName("spring");
        //When
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class,
                () -> memberService.join(member2));//예외가 발생해야 한다.
        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
    }
}
  • 통합 테스트
package hello.hellospring.service;
 
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
 
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
 
/*
 * spring 컨테이너와 DB를 연결한 통합 테스트
 * MemberServiceTest 와 기능은 동일함
 */
@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
 
    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;
 
    @Test
    public void 회원가입() throws Exception {
        //Given
        Member member = new Member();
        member.setName("hello");
        //When
        Long saveId = memberService.join(member);
        //Then
        Member findMember = memberRepository.findById(saveId).get();
        assertEquals(member.getName(), findMember.getName());
    }
 
    @Test
    public void 중복_회원_예외() throws Exception {
        //Given
        Member member1 = new Member();
        member1.setName("spring");
 
        Member member2 = new Member();
        member2.setName("spring");
        //When
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class,
                () -> memberService.join(member2));//예외가 발생해야 한다.
        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
    }
}

📝 마무리

위의 예시를 보면,
통합 테스트로 진행하면 전체적인 흐름을 쉽게 검증해볼 수 있는 것을 알 수 있다.
그렇다면 통합 테스트를 사용하면 되는데 단위 테스트를 따로 하는 이유는 뭘까?

👉🏻 통합 테스트는 어플리케이션의 설정이나 Bean을 모두 로드하기 때문에 단위 테스트에 비해 검증 시간이 오래 걸린다. 또한, 테스트 단위가 크기 때문에 디버깅이 비교적 어렵다.

profile
아주 사소하더라도

0개의 댓글

관련 채용 정보