[spring 입문] 회원 서비스 개발, 테스트

채원·2024년 1월 23일

스프링

목록 보기
5/18
post-thumbnail

출처) 인프런 스프링 입문 강의

회원 서비스 개발

회원 서비스 생성
이전에 생성한 도메인, 레포지토리로 비즈니스 로직을 작성

sr/cmain/java/hello.hellospring/service 패키지 생성
아래에 MemberService 클래스 생성

1) 회원 가입 기능

    /** 회원 가입 **/
    public Long join(Member member){
        // 같은 이름이 있는 중복 회원 X
        Optional<Member> result = memberRepository.findByName((member.getName()));
        result.ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });
        memberRepository.save(member);
        return member.getId();
    }

option + command + v 단축키: Optional ~ 자동 완성해줌
optional로 감싸면 메서드를 사용할 수 있음
ifPresent 메서드를 사용해서 값이 있으면 이미 존재하는 회원 (중복 가입 방지)임을 알림

더 깔끔하게 코드를 작성하는 방법

 memberRepository.findByName((member.getName()))
 	.ifPresent(m -> {
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });

result 변수에 저장하지 않고 조회 결과 값으로 메서드 호출

control+t 단축키: 원하는 코드 드래그 후 method 검색하면 메서드가 생성됨

2) 전체 회원 조회

서비스 클래스는 비즈니스 쪽 네이밍을 해야함
반면, 레포지토리 클래스는 단순한 기능 위주의 네이밍을 함
이미 레포지토리에 findAll 메서드를 만들어 두었기 때문에 호출 값을 리턴해줌

    /**
     * 전체 회원 조회
     */
    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

3) 아이디로 회원 조회

memberId로 회원을 조회하는 메서드
이미 레포지토리에 findById가 있으므로 호출 값을 리턴해줌

    /**
    * 아이디로 회원 조회하기
    */
   public Optional<Member> findOne(Long memberId){
       return memberRepository.findById(memberId);
   }

회원 서비스 테스트

위에서 생성한 회원가입 기능에서, 중복 가입인 경우 exception이 터지는지 테스트 해보기
클래스에서 cmd + shift + t 누르면 테스트 생성할 수 있음

테스트 라이브러리 Junit5 선택, 원하는 멤버 체크

test 폴더에 같은 service 패키지 안에 테스트 app이 생성됨

이제 각 멤버에 대해서 테스트 할 코드를 작성
테스트 코드는 빌드에 포함되지 않기 때문에 더 직관적인 코드를 원한다면
메서드 이름을 한글로 바꿔도 괜찮음

테스트에 앞서서 MemberService 객체부터 생성

given - when - then 문법

머리 가슴 배처럼 given, when, then으로 나눠 작성
어떤 걸 줬을 때 (given), 뭘 검증할 것인지 (when), 검증 결과 (then)
주석을 달아서 작성하는 것이 좋음

1) 회원가입 기능 테스트

Assertions에 assertions 없으므로 static import 해줌

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

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

class MemberServiceTest {
    MemberService memberService = new MemberService();

    @Test
    void 회원가입() {
        // given
        Member member = new Member();
        member.setName("hello");
        // when
        Long saveId = memberService.join(member);
        // then
       Member findMmember = memberService.findOne(saveId).get();
       assertThat(member.getName()).isEqualTo(findMmember.getName());

    }

처음 회원 가입하는 테스트
join 으로 회원 가입하고 리턴 받은 회원 아이디를 saveId에 저장
이후 저장된 멤버를 꺼내서 findMember에 저장하고, 가입한 멤버와 저장된 멤버가 일치하는지
isEqualTo로 검증

2) 중복 회원 가입 테스트

이름이 같은 멤버를 생성하고 join할 때 두 번째 멤버의 join에서 IllegalStateException 발생
e로 저장하고 getMessage 해서 검증하면 됨

    @Test
    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("이미 존재하는 회원입니다.");
    }

계속 테스트하다보면 이미 spring 계정이 있기 때문에 member1을 생성할 때부터 오류가 발생함
clearStore 해주는게 필요, 현재 코드에서는 service만 생성했기 때문에, 레포지토리도 가져옴

    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

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

그러나 memberService, memberRepository를 각각 만들면 현재 코드에서는 store가 static이라 상관이 없지만 아닌 경우에는 다른 DB가 되기 때문에 코드를 수정하는게 필요함
➡️ 같은 인스턴스를 사용하게 수정
MemberService에서 레포지토리를 new로 생성하는게 아니라, 외부에서 받아서 생성하는 걸로 수정함

    // 기존 코드
    // private final MemberRepository memberRepository = new MemoryMemberRepository();

    // 변경한 코드
    private final MemberRepository memberRepository;
    public MemberService(MemberRepository  memberRepository){
        this.memberRepository = memberRepository;
    }

MemberServiceTest 에서도 memberService 객체를 생성할 때 레포지토리를 넘겨줌
beforeEach로 테스트 시행 전에 새 레포지토리를 생성하고, memberService 생성자인자로 넘기기
Dependency Injection (DI) 라고함

	MemberService memberService;
    MemberRepository memberRepository;

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

전체 코드

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import 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 static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {
   MemberService memberService;
   MemberRepository 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");
       // when
       Long saveId = memberService.join(member);
       // then
       Member findMmember = memberService.findOne(saveId).get();
       assertThat(member.getName()).isEqualTo(findMmember.getName());
   }

   @Test
   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("이미 존재하는 회원입니다.");
   }
   @Test
   void findOne() {
   }
}

0개의 댓글