본문 바로가기
Framework/Spring

회원 서비스 테스트

by 파2RI 2024. 1. 9.

Test를 할 때에 아주 편한 단축키가 있다.

 

 

그림과 같이 클래스에 ctrl + shift + t를 해주면 Test 생성 창이 뜨는데,

이때 Test 할 메서드를 모두 선택하고 OK를 눌러주면 된다.

 

이렇게 하면 예쁘게 각 메서드의 Test 껍데기까지 포함해서 Test 클래스가 만들어진다.

package hello.hellospring.service;

import org.junit.jupiter.api.Test;

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

class MemberServiceTest {

    @Test
    void join() {
    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

 

 

그리고, Test 코드를 짤 때 유용한 논리단계가 있는데,

Given(무언가가 주어졌을 때) - When(이것을 실행했을 때) - Then(그러면 결과가 이렇게 나와야 한다.) 문법이다.

 

 @Test
    void join() {
        //given

        //when

        //then

    }

 

이렇게 주석을 깔고 하면 편하다.

 

 

1. join 메서드 Test

 

@Test
    void join() {
        //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());

    }

 

새 Member 객체를 만들고 setName을 한다.

join 메서드는 return 값이 Long Id이기 때문에 이 값을 받는데,

이 받은 Id에 해당되는 Member 객체가 getName을 했을 때 그 멤버와 같느냐

이 과정을 테스트하는 것이다.

 

그러면 초록 체크표시가 잘 뜬다.

 

 

BUT!!! Test에서는 예외 플로우가 매우 중요하므로 위 경우는 반쪽짜리 테스트이다.

 

 

1-2. ValidateDuplicateMember() 메서드 Test

 

 @Test
    public void  ValidateDuplicateMember(){
        
        //given
        Member member1 = new Member();
        member1.setName("Spring");
        
        Member member2 = new Member();
        member2.setName("Spring");
        
        //when
        memberService.join(member1);
        try{
            memberService.join(member2);
            fail();
        } catch(IllegalStateException e){
            assertThat(e.getMessage().isEqualTo("이미 존재하는 회원입니다."));
        }
        
        //then
    }

 

Member 객체를 두 개 만들고, 둘 다 이름을 동일하게 설정한다.

이때 member1이 join한 후, member2의 join을 try-catch문으로 나타낸다.

MemberService에서 뜨도록 설정한 텍스트가 e의 메세지와 일치하면 성공.

 

초록 체크가 잘 뜬다.

 

 

그런데 텍스트로 뜨는 것보다는 다른 방법이 있는데,

assertThrows 함수를 쓰는 방법이다.

 

assertThrows(이 Exception 이 발생해야 한다.class, () -> 이것을 동작할 때);

 

//when
        memberService.join(member1);
        assertThrows(IllegalStateException.class, () -> memberService.join(member2));

 

그러면 IllegalStateException이 잘 떠서 초록 체크표시가 나온다.

 

 

또 assertThrows의 장점은 뜬 Exception 메서지를 볼 수 있다는 것인데,

 

 assertThrows(IllegalStateException.class, () -> memberService.join(member2));

 

이 부분에 ctrl + alt + v 해주면

 

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

 

이렇게 자동 리턴이 된다.

 

//when

        memberService.join(member1);

        // ctrl+enter+v
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));

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

 

그리고 이 e에서 getMessage한 값이 "이미 존재하는 회원입니다."인 것이 확인되면,

성공이라고 할 수 있다.

 

 

여기에서도 사용한 repository를 clear해줘야,

Test 순서에 국한되지 않고 Test 할 수 있기 때문에 afterEach, clear 해주도록 한다.

 

    MemberService memberService = new MemberService();
    
    // 지금 repository가 존재하지 않기 때문에 아래 코드 추가
    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    @AfterEach
    // 메서드가 끝날 때마다 이것을 실행
    public void afterEach(){
        memberRepository.clearStore();
    }

 

clear를 해주고 싶지만 MemberService밖에 없기 때문에,

MemberRepository를 가져온다.

 

 

그런데, MemoryMemberRepository 클래스에서 사용하는 MemoryMemberRepository는 이름만 같기 때문에

static이 빠지면 다른 데이터베이스를 사용하는 문제가 될 수 있다.

 

그렇기 때문에 MemberService.java의 기존 부분을

private final MemberRepository memberRepository = new MemoryMemberRepository();

 

아래와 같이 바꿔주는 것이 좋다.

MemberRepository를 내가 넣어주는 것이 아닌, 외부에서 넣어주도록 하는 것이다.

 private final MemberRepository memberRepository;
    
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

 

 

그리고 MemberServiceTest.java에서

 

아래 부분을

    MemberService memberService = new MemberService();
    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

 

이렇게 @BeforeEach를 사용해 바꿔주면 된다.

    @BeforeEach
    public void beforeEach(){
        memberService = new MemberService(memberRepository);
        memberRepository = new MemoryMemberRepository();
    }

 

 

이렇게 바꿔주면 실행을 할 때마다 @BeforeEach가 실행되어

같은 MemoryMemberRepository 데이터베이스를 사용하게 된다.

(외부에서 MemoryMemberRepository를 넣어주기 때문)