스프링 회원 관리-2

윤재열·2022년 1월 31일
0

Spring

목록 보기
2/72
post-custom-banner

3. 회원 레포지토리 테스트 케이스 작성

개발한 기능을 실행해서 테스트 할 때 자바의 main 메서드를 통해서 실행하거나, 웹 애플리케이션의
컨트롤러를 통해서 해당 기능을 실행한다. 이러한 방법은 준비하고 실행하는데 오래 걸리고, 반복 실행하기
어렵고 여러 테스트를 한번에 실행하기 어렵다는 단점이 있다. 자바는 JUnit이라는 프레임워크로 테스트를
실행해서 이러한 문제를 해결한다.

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

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


// repository가 잘 동작하는지 test하는 테스트 코드
// 테스트 코드를 만들때 보통 똑같은 패키지 명으로 만듬
// 클래스 이름은 클래스명 + Test 붙여서!
// 굳이 public으로 안해도 됨. 다른 곳에서 가져다 쓸게 아니라서
// 테스트하는 코드를 먼저 만들고 구현을 하는걸 TDD라고 함
class MemoryMemberRepositoryTest {

    // 테스트 하기 위해 생성
    MemoryMemberRepository repository = new MemoryMemberRepository();

    // 모든 테스트는 순서가 보장이 안됨. 순서에 의존하지 않게 설계되어야 함.
    // 여러 test를 함께 돌리면 이전 테스트에서 저장된게 안없어져서 오류가남
    // 테스트 끝나면 데이터를 클리어해줘야함
    // 클리어하는 함수는 memoryRepository에 clearStore만듬
    // @AfterEach = 테스트 메서드들이 끝날때마다 할 동작을 정의
    @AfterEach
    public void afterEach() {
        repository.clearStore();
    }

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

        repository.save(member); // 저장

        // 저장한게 잘 들어갔는지 확인, 참고로 저장할때 id가 세팅됨
        // 반환타입이 Optional인데 Optional에서는 get으로 값을 꺼낼 수 있음, 좋은 방법은 아니지만 테스트 코드에선 이렇게 해도 괜춘
        Member result = repository.findById(member.getId()).get();

        // 검증 단계
        // 둘이 같은지 확인
        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();

        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();
        assertThat(result.size()).isEqualTo(2);
    }

}

4. 회원 서비스 개발

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

// service -> 비즈니스 로직을 작성하는 부분
@Service
public class MemberService {

    // final = 처음 초기화 할 때와 생성자에서만 값을 할당할 수 있음. 그 외의 경우 값 수정 불가
    private final MemberRepository memberRepository;

    /* final 변수 초기화를 생성자로 외부에서 넣어주도록 해줌. 이런걸 Dependency Injection이라고 함 */
    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    /* 회원 가입 */
    public Long join(Member member) {
        // 같은 이름이 있는 중복 회원 x
        validateDuplicateMember(member);

        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> { // 값이 있으면, ifPresent는 Optional로 한번 감싸서 return해줬기 때문에 쓸 수 있는 것
                    throw new IllegalStateException("이미 존재하는 회원입니다.");
                });
    }

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

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

5. 회원 개발 서비스 테스트

package hello.hellospring.service;

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

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository; // clear를 해주기 위해 가져옴

    @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 findMember = memberService.findOne(saveId).get();
        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);
        // assertThrows(이 예외가 터져야함, 이 로직을 실행할 때)
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));

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

        // 또다른 방법, 좋진 않음
//        try {
//            memberService.join(member2);
//            // 예외처리 안되고 그냥 넘어가 버리면 실패니까
//            fail();
//        } catch (IllegalStateException e) {
//            assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
//        }

        //then
    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}
profile
블로그 이전합니다! https://jyyoun1022.tistory.com/
post-custom-banner

0개의 댓글