백앤드/SpringBoot + Java 간간한 백앤드 예제

[SpringBoot + Java] 간단한 백엔드(test code)

맏리믓 2023. 7. 16. 19:12

들어가며

- 개발 한 기능을 테스트 하는 방법은 크게 두가지가 있다.

  . main 을 통해 실행 하는 등 실제로 실행 하는 방법

  . test 코드를 이용해 테스트 실행을 해 보는 방법

- 이번 시간에는 test 코드를 통해 기능이 재대로 개발 되었는지 오류 없이 실행 되는지 확인 해 보도록 하겠다.


test코드 디렉토리 구성

- main 디렉토리 아래 test 디렉토리에 main 과 유사하게 디렉토리를 구성 해 준다.

- 이번에는 저번 시간에 만들었던 repository 를 test 해 볼 것이기 때문에 이와 유사하게 구성 해 주고 test class 를 생성 해 준다.

 

- 코드를 작성 한다.

 . 방법은 @Test 를 통해 아래의 함수가 test 코드임을 암시 한다.

 . assertThat 을 통해 정상적인 값으로 실행 되었는지 확인 해 준다.

 . 여기서는 "assertThat(A).isEqulTo(B)" 를 통해 비교 하는데 말 그래도 A 와 B 가 동일한지 확인 하는 코드이다.

 

- repository 의 기능 save, findByName, findAll 을 테스트 해 줄 것이다. 

package com.example.learn_ex_member.repository;

import com.example.learn_ex_member.domain.Member;
import static org.assertj.core.api.Assertions.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

public class MemoryMemberRepositoryTest {
    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();
        assertThat(member).isEqualTo(result); // 기대값인 member 가 result 와 동일 한가?
    }

    @Test
    public void findByName(){
        // 우선 두 명의 회원 정보를 저장 함
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        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);
    }
}

- 위와 같은 방법으로 test 를 실행 시 개별 test code 를 실행하면 모두 문제 없이 실행 된다.

- 하지만 class 전체를 실행 하게 되면 에러가 뜨게 된다.

- 이는 findAll 과 findByName 에 둘다 member 변수를 저장 하는 과정이 있어 충돌이 나기 때문이다.

- 따라서 각 test 를 실행 한 후 clear 해 주는 과정이 필요하다.


AfterEach

- 위 기능을 제공해 주는 것이 바로 AfterEach 이다.

- 이는 각 test code 가 실행 완료 될 때 마다 실행 해 주는 것이다.

 

- 우선 repository 쪽에 메모리를 clear 해 주는 코드를 추가 해 준다.

//MemoryMemberRepository.java
public class MemoryMemberRepository implements MemberRepository {
	//...
    public void clearStore(){
        store.clear();
    }    
}

 

- 그 후 repositoryTest 코드에 AfterEach 를 추가해 준다.

package com.example.learn_ex_member.repository;

import com.example.learn_ex_member.domain.Member;
import static org.assertj.core.api.Assertions.*;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import java.util.List;

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

    @AfterEach
    public void afterEach(){ // test 하나가 끝나고 난 후 실행 할 것
        repository.clearStore(); // 하나의 함수를 실행 한 후 clear 필수
    }
	//...
}

- 이후 실행 하면 문제 없이 돌아 가는 것을 알 수 있다.

- 만약 기능에 문제가 생기면 에러가 뜬다.


main 코드와 Repository 일치

- 앞 시간에 Service 코드에서 Repository 를 받아 내부에서 넣어 준 적이 있었다.

- 그렇게 되면 Test 코드에서의 Repository 와 main 코드의 Service 코드의 Repository가 같아 지게 된다.

- 모든 코드 수행 전에 실행 되어야 하기 때문에 @BeforeEach 를 사용 하였다.

//MemberServiceTest.java
	@BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

Test code exception 상황 발생시키기

- test code 는 오류 없이 잘 돌아 가는지 확인 하기 위한 수단이기도 하지만 예외처리가 잘 되는지 확인 하는 수단이기도 하다.

- MemberService 코드중 중복 회원 가입을 시도할 경우 Exception 이 발생 하니 이를 이용하여 구현 해 보겠다.

- 그리고 test code 는 given, when, then 형식으로 자주 쓴다고 하니 그렇게 구현 해 보았다.

 

- 우선 정상 적일때는 단순히 Member 데이터를 만들어 save 시켜 주면 된다.

//MemberServiceTest.java
	@Test
    void join() {
        //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());
    }

 

 

- 에러 상황일 때는 동일한 이름의 회원을 가입 시키는 경우다.

- 방법은 두가지가 있는데 

 . try - catch 문을 사용해 join() 시 exception 여부와 이때의 message 를 비교 한다.

 . assertThrows를 사용하여 exception 여부와 이때의 message 를 비교 한다.

//MemberServiceTest.java
	@Test
    public void error_join(){
        //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));
        Assertions.assertThat(e.getMessage()).isEqualTo("존재하는 회원");
//        try{
//            memberService.join(member2);
//            fail("예외가 발생해야 합니다.");
//        } catch(IllegalStateException e){
//            Assertions.assertThat(e.getMessage()).isEqualTo("존재하는 회원");
//        }
    }

 

- 전체 코드

//MemberServiceTest.java
package com.example.learn_ex_member.service;

import com.example.learn_ex_member.domain.Member;
import com.example.learn_ex_member.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 java.util.Optional;

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

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository = new MemoryMemberRepository();

    //MemberService.java 의 Repository 와 동일한 객체를 사용 하기 위한 작업
    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

    @AfterEach
    public void afterEach(){ // test 하나가 끝나고 난 후 실행 할 것
        memberRepository.clearStore(); // 하나의 함수를 실행 한 후 clear 필수
    }

    @Test
    void join() {
        //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 error_join(){
        //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));
        Assertions.assertThat(e.getMessage()).isEqualTo("존재하는 회원");
//        try{
//            memberService.join(member2);
//            fail("예외가 발생해야 합니다.");
//        } catch(IllegalStateException e){
//            Assertions.assertThat(e.getMessage()).isEqualTo("존재하는 회원");
//        }
    }

}