goosegoose.DRAM
article thumbnail

기능이 원하는 대로 동작하는지 알아보기 위해 검증을 해야 한다. 이럴 때 테스트 케이스를 사용한다.

 

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

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

 

test - java - hello.hellospring(package) - repository(package) - MemoryMemberRepositoryTest(calss)를 하나 만들었다.

class MemoryMemberRepositoryTest {

    //검사할 class 이름
    MemoryMemberRepository repository = new MemoryMemberRepository();

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

        repository.save(member);
        Member result = repository.findById(member.getId()).get();
        //System.out.println("result = " + (result == member));
        //Assertions.assertEquals(member, result);

        assertThat(member).isEqualTo(result);
        //org.assertj.core.api
    }

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

        //shift+F6 == rename
        Member member2 = new Member();
        member2.setName("spring1");
        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("spring1");
        repository.save(member2);

        List<Member> result = repository.findAll();
        assertThat(result.size()).isEqualTo(2);
    }
}

 

순서대로 메소드를 실행하면 성공하지만, class를 통해 한번에 실행할 경우 (한 번에 검사할 경우) 

위처럼 오류를 보인다. 한 번에 실행할 경우 메서드 실행 순서가 보장되지 않아(메서드 별로 따로 동작) 객체에 의도한 값이 저장되지 않았기 때문이다. 이를 방지하기 위해 test를 할 때마다 저장된 값을 비워줘야 한다.  

 

이전에 만들었던 MemoryMemberRepository class에 아래 메소드를 추가한다.

다시  MemoryMemberRepositoryTest로 돌아와서 어노테이션을 통해 위에서 만들었던 메서드를 호출한다.

이럼 순서 상관없이 test 할 수 있다.

 

지금은 개발을 다 끝내놓은 뒤, 검증했다. 그러나 먼저 틀을 만들어 놓은 뒤(TestClass를 먼저 만들어 놓은 뒤), 구현할 class를 작성할 수도 있다. 이렇게 순서를 뒤집는 것을 TDD: 테스트 주도 개발이라고 한다.  

 

회원 서비스 개발

main - service(package) - MemberSevice(class)를 생성.

package hello.hellospring.service;

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

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

public class MemberService { // 비지니스 메소드

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    //회원가입
    public Long join(Member member){
        //같은 이름이 있는 중복 회원은 안돼
        validateDuplicateMember(member); // 중복 회원 검증
        memberRepository.save(member);
        return member.getId();
    }

    //ctrl + alt + M
    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                        .ifPresent(m -> {
                            throw new IllegalStateException("이미 존재하는 회원입니다.");
                            //Null일 가능성이 있는 경우 Optional로 한번 감싼뒤 반환. ifPresent 같은 함수 사용가능.
                        });
    }


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

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

 기능 별로 메서드를 작성했다. 이제 이걸 테스트 해봐야 겠다.

 

회원 서비스 테스트

편하게 test하는 다른 방법이 있다.  class 이름에 대고 ctrl + shift + T를 누르면

create new test를 누른 뒤 testing library는 JUnit5를 선택하고 ok를 누른다. 그럼 아래처럼 자동으로 test code가 생성된다.

이때, test 코드의 같은 경로로 생성된다. DI(Dependency Injection)을 위해 MemberService class를 아래 처럼 바꿔준뒤

위에서 생성한 테스트 코드를 아래처럼 작성했다.

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.*;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach(){// 실행전 MemoryMemberRepository 객체 생성후 이걸 넣어줌
        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);
        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

goosegoose.DRAM

@goosesong

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!