6.Spring(회원 관리 사이트 - 2)

박종현·2024년 1월 18일

스프링 프로젝트

목록 보기
6/14
post-thumbnail
-정영한님의 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술'로 공부중입니다.

🙍‍♂️회원 관리 사이트

저번 시간에는 도메인과 리포지토리를 완성했었다. 이제 서비스를 구현하고, 구현한 서비스, 도메인, 리포지토리를 테스트해볼 것이다.

✅서비스 구현

제공하는 서비스로는 회원가입, 전체 회원 조회 및, 특정 회원 조회를 제공 할 것이다.
소스코드로 알아보자.

//서비스 패키지에 생성.
import java.util.List;
import java.util.Optional;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;

public class MemberService {

    private final MemberRepository memberRepository;
    
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    /*
     * 회원 가입
     */
     
    public Long join(Member member){
        //중복 불가
        validateDuplicateMember(member);
        memberRepository.save(member);
        return member.getId();
    }

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

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

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findByID(memberId);
    }
}

처음 부분은 리포지토리 클래스를 만들고, 유연한 사용을 위해서 DI를 해준 것이다.

  • join은 회원 가입을 하는 함수로, 중복검사를 시행한 다음, 리포지토리에 저장한 후, ID를 반환해준다.
  • validateDuplicateMember는 중복을 검사하는 함수로, 입력받은 이름을 존재하는지 확인한 후, 에러를 출력해준다.
  • findMembers는 모든 리포지토리의 값을 출력해준다.
  • findOne은 입력받은 ID와 같은 값을 출력해준다.

✅완성한 소스코드 테스트

테스트를 실행할 때, 메인 메서드를 통해 실행하거나 웹 애플리케이션의 컨트롤러를 통해 기능을 실험해 볼 수 있다. 하지만 이런 방법은 준비 및 실행이 오래걸리고, 반복적으로 실행하거나 한번에 많은 테스트를 실행하기가 어렵다는 단점이 있다.java에서는 JUnit을 제공해준다. 숨겨진 단위 테스트를 끌어낸 후 정형화하여 단위 테스트를 쉽게 해주는 테스트용 Framework이다.

1. 리포지토리 테스트

//src/test/java하위폴더에 repository 패키지를 생성한다.
import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import hello.hellospring.domain.Member;

public class MemorymemberrepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();

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

    @Test
    public void save(){
        Member member = new Member();
        member.setName("spring");

        repository.save(member);

        Member result = repository.findByID(member.getId()).get();
        Assertions.assertThat(member).isEqualTo(result);
    }

    @Test
    public void findByName() {
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        Member result = repository.findByName("spring1").get();
        Assertions.assertThat(result).isEqualTo(member1);
    }

    @Test
    public void findAll(){
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        List<Member> result = repository.findAll();

        Assertions.assertThat(result.size()).isEqualTo(2);
    }    
}

만들어놓은 MemoryMemberRepository를 생성해준다.

  • save를 통해 member name이 잘 저장되고 불러와지는지 확인한다.
  • findByName을 통해 2가지의 이름을 저장하고, 같은 이름이 함수를 통해 잘 불러와지는지 확인한다.
  • findAll을 통해 모든 member가 잘 불러와지는지 확인한다.

🖐 여기서 assertions을 사용하게 되는데, 가정하고 있는 사실이 올바른 지 검사할 수 있도록 하기 위해서 존재하는 기능이다. assertThat은 타겟을 적은 후, 메서드를 통해 검사하게 된다. 장점으로는 에러 메세지, 실패 메세지가 확인하기 쉽게 나오게 된다. 문제뿐만 아니라 문제가 되는 값을 출력해준다.

소스코드를 실행시켜주면 test result에 잘 실행이 된건지 확인할 수 있다.

우측 아래에 성공과 실패가 나타나게 된다. 실패가 발생한다. 왜냐면 이미 존재하는 값이 문제가 되어 발생하는 것으로, 테스트 실행마다 저장되어있는 값을 비워주어야 한다.
✅ 이를 위해 사용되는 AfterEach라는 이노미테이션이다. 매 테스트마다 repository를 초기화해주고, 다음 테스트를 실행하게 된다. 적힌 소스코드에서 AfterEach부분의 주석처리를 지운다면 잘 실행이 되는 모습을 볼 수 있다.

2.서비스 테스트

//src/test/java하위폴더에 service 패키지를 생성한다.

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

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

public class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository repository;

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

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

    @Test
    void join() {
        //given
        Member member = new Member();
        member.setName("hello");

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

        //then
        Member findMember = memberService.findOne(saveId).get();
        Assertions.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("이미 존재하는 회원입니다.");
        
        // try{
        //     memberService.join(member2);
        // }catch(IllegalStateException e){
        //     assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
        // }
        //then
    }
}

MemoryMemberRepository와 MemberService를 선언해준다.

  • join을 통해 맴버를 회원가입하고, ID를 만들어주는 과정을 확인한다.
  • 중복 예외 확인을 통해 같은 이름의 맴버를 2개 만들고, 두 번 저장할 때, 예외가 발생
    하는지, 원하는 예외인지 확인한다.

🖐 이전 테스트와는 살짝 다른점이 beforeEach를 활용하는 건데, 각 테스트 시작하기 전에, 실행할 코드들을 적어주는 것이다.

마무리

이것으로 도메인, 리포지토리, 서비스 부분을 소스코드로 구현해보는 과정을 거쳤다. 모르는 함수들이 대거 등장해서 많은 어려움을 겪었고, 프론트앤드처럼 바로바로 시각적으로 뭔가 나타나는게 없다보니까 되긴되었네...?하는 느낌이 강하지만, 계속 공부해가면서 프론트와 합쳤을 때를 생각하며 꾸준히 공부하려고 한다.

0개의 댓글