SPRING 입문 [ 코드로 배우는 스프링 부트 ]

[스프링 입문] 섹션 3.5 회원 관리 예제 (회원 서비스 테스트)

wlalsu_u 2023. 1. 10. 03:36

3.5.1  회원 서비스 테스트 코드 작성

 

 

앞서 섹션 3.4 에서 작성한 ' MemberService.java ' 가 정상적으로 작동하는지 확인하기 위한 test code 를 작성해보자.

 

 

먼저, test  >  java  >  hello.hellospringservice 패키지를 만든다.

service 패키지에 MemberServiceTest 클래스를 만들고 아래와 같이 코드를 작성한다.

 

 

 

 

코드를 작성하기 전에,

given / when / then 패턴을 사용하면, Test Code 를 보다 쉽게 이해할 수 있다.

 

아래의 코드들도 다음과 같은 패턴을 사용하여 작성하였다.

 

 

 

Given / When / Then 패턴으로 테스트 코드 작성

 

- Given : 어떠한 상황이 주어졌을 때,

 

- When : 어떠한 코드를 실행하면

 

- Then : 어떠한 결과가 나와야 함

 

 

 

 

 

1) 회원 가입 시 repository에 저장 여부 test

 

 

먼저, 회원가입에서 중복 체크는 제외하고,

 

저장한 정보가 Repository 에 있는지를 확인하는 코드를 작성해보자.

 

 

    @Test
    void 회원가입(){
        // 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());
    }

 

 

1) member 객체 생성

 

2) member 객체의 이름으로 "hello" 저장

 

3) member 객체 회원가입, saveId 에 저장

 

4)  member의 이름과, 실제 회원가입 시 저장된 이름이 같은지 확인

 

 

 

 

+ ) test code 의 경우 코드의 직관적 이해를 위해, 한글도 많이 사용한다.

 

 

 

 

test code 를 실행해보면, 정상적으로 작동하는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

2) 회원 가입 중복 체크 Test

 

 

 

join() 메소드의 핵심은, 

회원 가입 시 정보가 제대로 저장되는지 보다,

 

중복 회원 로직이 제대로 작동하는지 테스트 하는 것이다.

 

 

아래의 코드는, 

join() 메소드의 중복 이름 회원 로직을 확인하는 test code 이다.

 

 

 

    @Test
    public void 중복_회원_예약(){
        // given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

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

        // then

    }

 

 

 

1) 이름이 "spring" 으로 동일한 2개의 객체 생성

 

2) 이름이 "spring" 인 member1 을 repository 에 저장 ( 중복 발생 X )

 

3) 이름이 "spring" 인 member2 를 repository 에 저장( 중복 발생 O )

 

   :  assertThrow 를 사용하여 validDuplicateMember (회원 중복 확인) 에 의해 예외가 발생하는 것을 확인

 

 

 

 

 

 

test code를 실행해보면, 제대로 작동하는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 

 

중복 회원 체크 test code 는 아래와 같은 try - catch 문으로도 작성할 수 있다.

 

 

 

        try {
            memberService.join(member2);
            fail();
        }catch (IllegalStateException e){
            Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");

 

 

 

1) member2 를 repository 에 저장 ( 중복 발생 )

 

2) 중복이 발생한 경우 fail()

 

3) Assertions 를 사용하여, 회원 중복 시 출력되는 메시지 동일 여부 확인

 

 

 

 

 

try - catch 로 작성하였을 때도, 아래와 같이 test 에 성공하는 것을 확인할 수 있다.

 

 

 

 

 

 

 

클래스 전체의 test code를 돌려보아도,

아래와 같이 모두 성공적으로 test 되는 것을 확인할 수 있다.

 

 

 

 

 

 

 

 

 


 

3.5.2  clear 메소드 작성

 

 

앞서 회원 가입에서, 다음과 같이 객체 이름을 변경하면

test 에 fail 하게 된다.

 

member.setName("spring")

 

 

이는 DB에 값이 계속 누적되고 있으므로,

 

중복_회원_예약() 시에, 이미 "spring" 으로 저장된 이름이 있기 때문이다.

 

섹션 3.3 에서 설명한 바와 같이,

test code 를 수행할 때마다, DB를 초기화 하기 위해서는 clear 메소드를 추가해 주어야 한다.

 

 

 

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

 

 

먼저, memoryMemberRepository 를 가져오고,

 

기존의 memberRepository 클래스의 clearStore() 함수를 사용하여 간단하게 작성할 수 있다.

 

 

( 섹션 3.3 참고)

 

 

 

 


 

 

MemberService.java 전체 코드

 

 

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;

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

public class MemberService {

    private final MemberRepository memberRepository;

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

    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

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

 

 

 

 

MemberServiceTest.java 전체 코드

 

 

package hello.hellospring.service;


import hello.hellospring.domain.Member;
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.junit.jupiter.api.Assertions.assertThrows;



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("spring");

        // 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);
        assertThrows(IllegalStateException.class, () -> memberService.join(member2));

        // then

    }

    @Test
    void findMembers(){

    }

    @Test
    void findOne(){

    }
}

 

 

 

 

 

 

 

 

 

김영한 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 강의를 기반으로 작성하였습니다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard