TIL - JAVA spring DAY 7

jihan kong·2022년 1월 11일
0

JAVA spring 입문

목록 보기
8/20
post-thumbnail

지난 시간까지 회원 서비스를 개발하였다.

회원서비스 개발 과정

이제 Test하는 프로세스를 거쳐 서비스의 완전성을 보장해야한다.

intellij 툴에서 Test case를 생성할 수 있는 단축키 alt + enter (Mac/Linux : cmd + shift + T)를 통해 조금 더 간편하게 Test case class를 만들어낼 수 있었다.

Hotkey is God

이 후, 만들어진 MemberServiceTest class를 강사님이 코딩하시는 것을 따라하며 개발해보았다. 매 강의를 들을 때마다 느끼는 것이지만 class 하나를 만들때도 강사님은 머릿속에 어떤 멤버변수들이 들어갈 것인지, 어떤 객체를 생성해낼것인지, method를 어떻게 구성해야하는지를 다 그려놓고 하시는 느낌이었다. 강사님의 강의를 들으면서 내가 부족한 부분들이 많이 보였고, 컴퓨팅사고의 능력을 기르는 기본기부터 다져야겠다는 생각을 하게 되었다.

각설하고

회원서비스 테스트 코드를 살펴보자.

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.Test;

import java.util.Optional;

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

class MemberServiceTest {

    MemberService memberService = new MemberService();
    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    @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();
        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);
            fail();
        } catch (IllegalStateException e) {
            assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
        }
        */

        // then
    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

( 시작하기에 앞서 메소드 이름을 한글로 한 것을 볼 수 있는데 테스트 코드의 경우, 빌드할때 실제 코드에 포함되지 않기 때문에 조금 더 직관적이게 한글로 생성한다고 한다. )

  • void 회원가입( )

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

이 때, 강사님께서 테스트 케이스를 작성하는 방식 중 하나를 소개해주셨다.

Given - When - Then

Given : 테스트를 위해 전제(준비)된 것. (무엇인가가 주어짐)

When : 실제 테스트. (이를 실행)

Then : 테스트 검증. (결과 도출)

거의 모든 테스트는 이렇게 구성된다고 해도 과언이 아닐정도로 정형화된 패턴 구성이라고 하셨다. 따라서 이 방식으로 테스트 코드를 작성해보았다.

  • given: 테스트를 위한 준비물이 필요한 셈이므로 우리가 테스트 하고자할 member 객체를 생성했다. (이름은 setName을 통해 "hello"로 설정)
  • when: 실제 리포지토리에 저장될 saveId 변수에 memberService 가 잘 기능하는지 join하여 테스트할 것이므로 Long saveId = memberService.join(member); 와 같은 식으로 작성한다.
  • then: 이 메소드를 테스트하기 위해서는 어떤 것이 필요한지 생각해보았다. 결국, 우리가 저장을 한 변수가 repository에 있는지를 찾아보려고 하는 것이다. 따라서, findMember라는 객체를 생성하고 memberService class 에서 findOne(saveId).get(); 저장한 saveId를 넘기고 get으로 받았다.
    그 후, assertThat 을 통해 member class에 getName으로 받은 내용이 새로 만든 findMember class에 getName으로 받은 내용과 같은가를 검증해보았다.

이렇게 테스트가 끝나면 좋겠지만 사실 아직 미완성이라고 볼 수 있다. 코드를 테스트할 때, 정상적인 동작을 하는지에 관한 테스트도 중요하지만 exception 을 캐치하는 부분도 상당히 중요하다. 우리 서비스에서는 중복회원을 예외로 하기로 했었다. 따라서 이를 테스트할 코드도 필요하다. 다음의 코드가 바로 그것이다.

  • public void 중복회원예외 ( )

     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);
             fail();
         } catch (IllegalStateException e) {
             assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
         }
         */
    
         // then

    생성된 객체 member1과 member2의 setName을 "spring"으로 동일하게 define할 경우, memberService.join(member1) 까지는 문제가 되지 않는다. 그러나 두번째 join인 memberService.join(member2) 일 때, 바로 member1 과 중복이 발생되고 예외처리를 해주어야한다. 예외처리 방법 중 하나로 try, catch 문을 사용할 수도 있다. (주석처리한 부분 참고)

    그러나, 강사님께서 알려주신 더 좋은 문법을 사용해보도록 하였다. assertThrows 가 바로 그것이다. 이번에 처음 알게되어 자세히는 모르지만, () -> memberService.join(member2) 로직이 실행된다면 IllegalStateException.class 예외가 발생해야함을 의미하는 것 같았다. 메세지로 검증하는 것은 위 회원가입 메소드와 동일하게 assertThat 으로 처리하면 된다.

The end...?

(이렇게 해서 Test code 개발이 모두 끝났다) 라고 말하고 싶지만.... 아직 끝나지 않았다. 전에 테스트 코드를 만들때 했던 것처럼 DB를 clear 하는 작업메모리 참조에 관한 이슈가 남았다. 이 내용은 다음 포스팅에서...

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글