[Spring Introduction] 스프링 통합 테스트

Hyeri·2021년 2월 17일
1

Spring Introduction

목록 보기
3/4
post-thumbnail

-인프런에서 김영한강사님의 스프링 강의를 들으며 정리하는 노트-
code: github.com/hyeriful/hello-spring/tree/master/src/test/java/com/hello/hellospring/service

MemberServiceIntegrationTest .java

package com.hello.hellospring.service;

import com.hello.hellospring.domain.Member;
import com.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;

@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {

    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;

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

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

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

    @Test
    public void 중복_회원_예외() {
        //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("이미 존재하는 회원입니다.");

        //then
    }
}

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


여기서 잠깐! DB transaction에 대해 간단하게 알고가자!
디비는 transaction이라는 개념이 있다.
디비에 데이터를 insert query 한다음에 commit을 해줘야 디비에 반영이 되고
테스트 한다음에 roll back하면 데이터베이스에서 데이터가 없어진다.(반영을 안한다)
이렇게 해서 검증할 수 있는 방법이 @Transactional

테스트를 실행할 때 각 테스트 메소드마다 먼저 transaction을 실행하고
디비에 데이터를 insert query하고 다 넣은 다음에
테스트가 끝나면 roll back한다.


MemberServiceTest.java

package com.hello.hellospring.service;

import com.hello.hellospring.domain.Member;
import com.hello.hellospring.repository.MemoryMemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;


import java.util.Optional;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memoryMemberRepository;

    @BeforeEach //각 method시작 전에 실행
    public void beforeEach() {
        memoryMemberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memoryMemberRepository);
    }

    @AfterEach
    public void afterEach() {
        memoryMemberRepository.clearStore();
    }

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

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

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

    @Test
    public void 중복_회원_예외() {
        //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("이미 존재하는 회원입니다.");

        //then
    }
}

순수하게 자바 코드로 짜면서 최소한의 단위로 하는 것: 단위 테스트 (MemberServiceTest 파일 해당)
스프링 컨테이너와 디비까지 연경한 것: 통합 테스트 (MemberServiceIntegrationTest 파일 해당)

순수하게 자바 코드로 짠 MemberServiceTest를 보면 @BeforeEach 통해서 각 method 시작 전에 객체를 새로 생성하고 @AfterEach 통해 해제하는 코드가 있다. 통합테스트에서는 @Transactional를 사용함으로써 이러한 코드를 생략할 수 있지만 가급적이면 단위 테스트가 좋다고 한다. 단위 테스트가 속도 훨씬 빠르고 단위 테스트로 잘 돌아가지 않으면 잘못 코드를 짰을 가능성이 크다고 한다. 아직 잘 와닿진 않는다..🤪

profile
아무거나 내가 적고 싶은거 🤟

1개의 댓글

comment-user-thumbnail
2022년 3월 30일

좋은 정보 잘 보고 갑니다.
감사해요

답글 달기