스프링 DB 접근 기술 - 스프링 통합 테스트

Chooooo·2022년 8월 12일
0
post-thumbnail

스프링 통합 테스트

회원 관리 예제 - 백엔드 개발에서 진행했던 테스트는 스프링을 띄우지 않고 진행했던 순수한 자바 코드로 진행한 단위 테스트였어.
DB연결을 했으니 이제 스프링 컨테이너와 DB를 연결하여 실행하는 통합테스트를 진행해보자!!


스프링 컨테이너와 DB까지 연결한 통합 테스트

스프링 부트를 통한 테스트

클래스 앞에 어노테이션을 붙여줘

@SpringBootTest
스프링 컨테이너와 테스트를 함께 실행한다
@Transactional
테스트 케이스에 이 애노테이션이 있으면, 테스트 시작 전에 트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백한다. 이렇게 하면 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않는다.

test/java/hellospring/service에 MemberServiceIntegerationTest 파일 생성하고 코드 작성.

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
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.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

    @Test
    void 회원가입() {
        //given
        Member member = new Member();
        member.setName("spring");

        //when
        Long saveId = memberService.join(member);

        //then
        Member findMember = memberService.findOne(saveId).get();
        assertEquals(member.getName(),findMember.getName());
    }

    @Test
    void 중복_회원_예외(){
        //given
        Member member = new Member();
        member.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member);
        IllegalStateException e = assertThrows(IllegalStateException.class,
                ()->memberService.join(member2));

        //then
        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다");
    }
}

회원가입, 중복회원예외 테스트 코드는 이전 테스트와 동일한 코드
@SpringBootTest를 사용하면 스프링 컨테이너와 테스트를 같이 실행해!
이전에는 @BeforeEach를 사용해 각 테스트를 실행하기 전 회원 서비스와 리포지토리를 직접 객체 생성, 주입했지만 이제는 @SpringBootTest와 @Autowired를 사용해 컨테이너에서 스프링을 통해 서비스와 리포지토리를 주입할 수 있게 됐다.
(MemoryMemberRepository에서 MemberRepository로 변경, 구현체는 SpringConfig에서 가지고 오게 된다. + ClearStore()는 @Transactional에 의해 필요가 없어졌어.)

//변경사항.
@Autowired MemberRepository memberRepository; //MemoryMemberRepository에서 변경

//아래 코드 삭제해도 된다.
/*    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
    
    @AfterEach
    public void afterEach() {
        memberRepository.clearStore();
    }
*/

테스트 실행

우선 회원가입 메서드를 테스트해보면 오류가 발생해. 이는 데이터베이스에 Spring이라는 이름이 이미 존재하기 때문(저번에 이미 넣었잖아) 데이터베이스의 데이터들을 우선 삭제하자.

테스트가 한 번 실행하면 테스트하는 데이터가 DB에 저장되고, 이를 다시 테스트할 때 중복 데이터로 인식하는 문제가 발생할 것이다.

@Transactional
테스트는 반복할 수 있어야한다. 테스트를 실행하면 트랜잭션이 실행되고 데이터가 DB에 저장되는데, 테스트가 끝나면 이를 롤백해주어 데이터를 삭제한다. DB에 실제 데이터가 저장되지 않음을 확인할 수 있어.
즉, @Transcational을 사용하면 트랜잭션 수행 후 롤백을 수행하여 테스트를 수행해도 DB에는 데이터가 반영되지 않는다--> 그러므로 다음 테스트 또한 영향을 받지 않아!!


이전까지 수행한 테스트는 단위 테스트야
단위 테스트는 MemberServiceTest와 같은 순수한 자바 코드로 이루어진 최소 단위의 테스트
통합 테스트는 이번 장에 수행한 스프링 컨테이너, DB등을 연동한 테스트

진짜 좋은 테스트는 단위테스트를 잘 만드는 게 훨씬 더 좋은 테스트일꺼야

이 글은 강의 : 김영한 - "스프링 입문-코드로 배우는 스프링 부트, 웹 MVC, DB접근기술"을 듣고 정리한 내용입니다.

profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글