[백엔드 첫 걸음] 스프링 통합 테스트 - (회원 관리 예제)

khyojun·2022년 8월 4일
0

Spring 시작

목록 보기
15/15
post-thumbnail

1. 스프링 통합 테스트

이전의 테스트에서는 순수 java코드로만 구성되어져있는 테스트코드를 만들었었는데 이번에는 저번 시간에 연결한 db와 연동하여 테스트하기위해 Spring과 연결된 테스트코드를 만들어보는 시간이었다.

📂 test/java/service/MemberServiceIntegrationTest

package com.example.demo_practice.service;

import com.example.demo_practice.domain.Member;
import com.example.demo_practice.repository.MemberRepository;
import com.example.demo_practice.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.assertThrows;


@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {

    @Autowired MemberService memberService;
    @Autowired MemberRepository memberRepository;




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

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

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



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


    }

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

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

        //when
        memberService.join(member);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
        assertThat(e.getMessage()).isEqualTo("이미 존재하는회원입니다.");

        //then

    }


}

코드를 확인하여보면 이전에 작성하였던 MemberServiceTest를 그대로 가져왔는데 여기서 차이가 나는 부분이 있다.

  1. @SpringBootTest
  2. @Transactional
  3. @Autowired

@SpringBootTest

SpringBootTest를 선언하게 되면 순간적으로 이 테스트를 스프링 컨테이너와 함께 실행을 시키게된다. 그렇게 되면은 아까 처음에 말했던 우리가 연결한 h2데이터베이스와 다른 이전의 Bean으로 올렸던 것과 함께 바로 테스트를 수행할 수 있게 된다.

@Transactional

이전 테스트 코드들에서는 beforeEach, afterEach가 해당하는 코드들이 있었다. 각각의 이유가 있었지만 테스트가 진행이 되기전 MemoryMemberRepository과 service가 가리키는 저장소를 같게 하기 위해 DI를 하기 위한 이유가 있었다. 그러나 Transactional을 사용하게 되면 테스트 시작 전에 *트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백을 하게 된다. 이렇게 하게 되면 이전 aftereach를 사용하던 clear과 같은 작업을 수행할 필요가 없어진다. 즉, DB에는 데이터가 남지 않게 된다는 얘기여서 다음 테스트에 영향을 주지 않는다는 뜻이다.

트랜잭션?

트랜잭션(Transaction)은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다.

@Autowired

여기서도 Autowired를 사용하였는데 이전과는 다르게 그냥 필드에서 Autowired를 선언하여 DI를 시켜주었다. 그치만 전에 말했듯이 필드에서 Autowired를 하게 되면 변경사항이 생길경우 변경할 수가 없어 기본적으로는 Constructor를 생성하여 DI를 한다고 하였다.
그치만 테스트환경과 같은 경우에서는 다음과 같은 테스트코드 안에서는 딱히 변경하지 않아도 DI만 시켜주는 역할만 하기 때문에 필드에서의 DI를 하였다.

알게 된 점

  1. 통합테스트

참고

김영한 - 스프링 입문 강의

profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글