[백엔드 첫 걸음] 회원 서비스 테스트, DI - (회원 관리 예제)

khyojun·2022년 7월 22일
0

Spring 시작

목록 보기
10/15
post-thumbnail

1. 회원 서비스 테스트

📂 test/java/service/MemberServiceTest.java

🏸 Tip

기존에 있던 MemberServic의 테스트를 활용해야하는 부분이기에 Intellij에서는 Ctrl + Alt + T를 class명을 지정후 누르게 되면 바로 Test파일에 해당 class의 test를 만들 수 있다.

package com.example.demo_practice.service;

import com.example.demo_practice.domain.Member;
import com.example.demo_practice.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 static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

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

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

    @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
        //        try {
//            memberService.join(member2);
//            fail();
//        } catch(IllegalStateException e){
//            assertThat(e.getMessage()).isEqualTo("이미 존재하는회원입니다.");
//        }
// 위를 개선하여 아래의 코드로 

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

        //then

    }


    @Test
    void findMembers() {
    }

    @Test
    void findOneMember() {
    }
}

🏸 코드 분석

  1. 이번 Test문들을 실습해보면서 봐야할 것이 생각보다 있었다. 위의 코드들을 보게 되면 이곳은 테스트의 공간이기에 함수명을 만들때 외국어를 굳이 쓰지 않아도 어렵지 않은 상황에서는 한국어를 사용하여 함수명을 정하여 알아보기 쉽게 만들 수 있다는 점이 있었다.

  2. 항상 테스트 코드를 작성하였을때는 모든 경우의 수들에 대해서 알아봐야 한다. 그러므로 회원가입을 할 때 추가적으로 발생할 수 있는 중복 회원일때의 경우도 생각하여 테스트를 진행하여야 했다.

  3. 기존 같으면 오류가 발생하는것을 확인할 때는 try catch문을 활용하였을테지만 assertions의 assertThrows를 활용하여 알아보는 것이 더 코드가 간결해지고 편하게 확인할 수 있었다.

  4. 테스트 코드를 작성할 때는 강의에서 들은바 given, when, then 절을 활용하여 작성하게 되면 더 효율적으로 코드를 확인하고 알아볼 수 있다고 하였다. 이 부분은 뒤에서 알아보자.

  5. 이번에도 AfterEach 를 활용하여서 테스트 코드를 진행할때마다 repository에 중복적으로 member가 추가되는 것을 막기 위하여 clearstore를 추가하였다.

  6. BeforeEach를 이번엔 사용을 하게 되었는데 기존 memberService는 새로운 인스턴스를 만들어 사용한 반면 이번에는 memberService 인스턴스를 만들때 memberRepository가 추가적으로 들어가야했다.
    그래서 그 아래의 코드를 보면 MemberService 클래스에 생성자가 추가 되며 뒤에 주석으로 DI라고 붙여주었다.

	MemberService memberService;
    MemoryMemberRepository memberRepository;
    
    @BeforeEach
    public void beforeEach()
    {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
  ---------------------------------------------------------------------------------  
    	// java/service/MemberService
     	private final MemoryMemberRepository memberRepository;

    	public MemberService(MemoryMemberRepository memberRepository){// DI
        this.memberRepository = memberRepository;
    }
    

기존과 같이 진행을 하였을때는 다음과 같은 문제가 있었다.

테스트코드의 MemoryMemberRepository라는 새로운 인스턴스를 만들게 되었을때, 기존 memberservice에서 참고하는 MemoryMemberRepository랑은 실질적으로는 다른 곳이다. 그렇기에 MemberService에서 확인하는 MMR(MemoryMemberRepository)랑 테스트코드의 MMR을 일치시켜줄 필요가 있었다.

그리하여 MemberService의 입장에서 MMR을 주입시켜서 만들 필요가 있었다. 이러한 과정을 DI(Dependency Injection)이라고 한다. 이것도 밑에서 한 번 알아보자.


🏸 given when then?

Given

 테스트에서 구체화하고자 하는 행동을 시작하기 전에 테스트 상태를 설명하는 부분

When

 구체화하고자 하는 그 행동

Then

 어떤 특정한 행동 때문에 발생할거라고 예상되는 변화에 대한 설명

Given
테스트를 위해 준비하는 과정입니다. 테스트에 사용하는 변수, 입력 값 등을 정의하거나, Mock 객체를 정의하는 구문도 Given에 포함됩니다. 참고로 아래 그림을 참고하면 when이라는 메서드도 Given에 포함되었는데 해당 구문은 테스트 준비를 위한 것이기 때문에 Given에 포함되는게 맞다고 생각합니다.
When
실제로 액션을 하는 테스트를 실행하는 과정입니다. When은 가장 중요한 구문이지만 다른 구문들에 비해 가장 짧습니다.
Then
마지막은 테스트를 검증하는 과정입니다. 예상한 값, 실제 실행을 통해서 나온 값을 검증합니다.

🏸 DI?

DI : Dependency Injection(의존관계 주입)

DI(의존관계 주입)는 객체가 의존하는 또 다른 객체를 외부에서 선언하고 이를 주입받아 사용하는 것이다.

이렇다고 하는데 위에서의 의존관계는 MemberService와 MemoryMemberRepository이다. 즉 MMR(MemoryMemberRepository)는 Service의 입장에서 보면 외부에서 주입당하였다. 그러므로 아까 말했던 Member의 저장소가 service와 따로 놀지 않도록 의존관계를 넣어준 것이다.

DI의 장점

  1. 의존성이 줄어든다.

  2. 재사용성이 높은 코드가 된다.

  3. 테스트하기 좋은 코드가 된다.

  4. 가독성이 높아진다.

DI에 대해서는 이후 더 깊게 알아볼 수 있도록 하겠다.

참고

김영한 - 스프링 입문 강의
DI - Tecoble

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

0개의 댓글