[Spring] 입문 3-3. 회원 레포지토리 테스트 케이스 작성

강우엉·2023년 6월 22일

Spring

목록 보기
9/359

💡 테스트 코드란?

앞서 만들었던 코드들의 기능이 제대로 작동하는지 확인을 하는 방법은 다양하다.

  • main 메서드를 통해서 실행
  • 컨트롤러를 통해서 해당 기능을 실행

이러한 과정은 오래걸리고 반복적으로 실행하기에 어렵다는 단점이 있다.

따라서 우리는 jUnit 이라는 프레임워크를 통해 테스트코드랄 작성할것이다.

💡 테스트 코드 작성하기

먼저 테스트 코드를 작성할 Class를 만들어준다.
보통 테스트코드의 클래스 이름은 뒤에 test만 붙여주는것이 관례이다.
따라서 우리는 test 폴더에 repository package를 생성하고, 해당 패키지에
MemoryMemberRepositoryTest라는 클래스를 생성한다.

그리고 해당 클래스에서 MemoryMemberRepository의 기능을 확인하기에
객체를 만들어준다.

class MemoryMemberRepositoryTest {
    // 테스트 할 기능이 담긴 객체 생성
    MemoryMemberRepository repository = new MemoryMemberRepository();

}

💡 save 기능 테스트

이제 save의 기능이 제대로 구현되는지 테스트해보자.
test를 하기 위해서는 test할 메서드 위에 @Test 라는 어노테이션을 붙여줘야한다.
junit.jupiter.api에 포함된 메소드로, 단위 테스트임을 명시해줘 독립적으로 실행이 가능하다.

class MemoryMemberRepositoryTest {
    MemberRepository repository = new MemoryMemberRepository();

    @Test
    public void save(){
    }
}

계속해서 테스트 코드를 작성해보자
1. 멤버 객체를 생성하고, 테스트를 위해 spring 이라는 이름을 세팅해준다.
2. repository에 해당 값을 저장한다.
3. 저장이되었는지 확인하기 위해 member.getId에 해당하는 member 객체를 findById를 통해 찾아와 result에 저장한다.
4. member와 result가 같다면 기능이 정상 작동하는것이기에 두 객체가 같은지 확인한다.

    @Test
    public void save() {
        Member member = new Member(); // 멤버 객체 생성
        member.setName("spring"); // 멤버의 이름 세팅

        repository.save(member); // repository 에 저장

        Member result = repository.findById(member.getId()).get(); // optional 에서 get 을 사용하여 값 꺼냄
        //System.out.println("result = " + (result == member));
        //Assertions.assertEquals(member, result); // org.junit.jupiter 가 제
        assertThat(member).isEqualTo(result); // org.assertj 가 제공 (member 와 result 같은지 비교)
    }

save 메서드가 잘 작동하는걸 확인 할 수 있다.

💡 Assertions를 이용하여 객체 비교

위의 코드는 정상 작동하지만 중요하게 봐야할 부분이있다.
두 개의 객체를 비교하는 부분을 보면 주석 포함 3개의 방법으로 비교를 했다.
첫번째 방법으로 System.out.println을 하는 방법은 테스트 코드의 수가 많아지면 계속 확인하는데 불편함이 있다 . 이럴때 assert라는 기능을 사용한다.

assert란?
jUnit에서 테스트에 넣을 수 있는 정적 메서드 호출이다.
어떤 조건이 참인지 검증하며 테스트 케이스 수행 결과를 판별하는 역할을 한다.

  1. assertEquals() 이용
public void save(){
    Member member = new Member();
    member.setName("spring");

    repository.save(member);

    Member result = repository.findById(member.getId()).get();
    Assertions.assertEquals(member, result);
}

assertEquals(expect, actual) 의 형태로써, 앞에 기댓값과 뒤에 actual값이 같은지 확인한다. 두 개의 객체가 같다면 테스트를 통과한다.

  1. assertThat() 이용
public void save(){
    Member member = new Member();
    member.setName("spring");

    repository.save(member);

    Member result = repository.findById(member.getId()).get();
    Assertions.assertThat(member).isEqualTo(result);
}

assertThat(actual).isEqualTo(expected) 의 형태로써, assertEquals와 같이 두 객체가 같은지 확인하고, 같다면 통과한다.

assertThat()을 이용한 방법이 가독성, 안정성 등 다양한 측면에서 나은 점이 많아 assertThat()을 이용한다고 한다.

참고로 assertThat 앞에 Assertions는 아래와 같이 static import를 하여 생략하여 사용 가능하다.

import static org.assertj.core.api.Assertions.*; 
// static import로 assertThat 바로 사용 가능

💡 findByName 기능 테스트

findByName 기능을 테스트해보자.
1. member1, member2 객체 2가지를 생성하고 각각 spring1, spring2라는 이름을 설정한다.
2. findByName("spring1")을 통해 sprig1로 설정한 객체를 result에 저장한다.
3. assertThat()을 이용하여 result와 member1이 같은지 비교한다.
결과가 같다면 findByName도 제대로 작동하는 것이다.

 @Test
    public void findByName() {
        Member member1 = new Member();
        member1.setName("spring1"); // 멤버1에 스프링1
        repository.save(member1); // repository 에 저장

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);
        
        // 2개의 회원가입

        Member result = repository.findByName("spring1").get(); // 스프링1을 찾음
        assertThat(result).isEqualTo(member1); // result 와 member1이 같은지 비교
    }

💡 findAll 기능 테스트

findAll 기능을 테스트해보자.
1. member1, member2 2개의 객체를 생성하고 이름을 각각 spring1, spring2로 설정한다.
2. 메모리 저장소에 2가지 객체를 저장한다.
3. List형식의 result 객체에 findAll 결과를 저장한다.
4. assertThat을 이용하여 result의 사이즈가 2인지 확인한다.
사이즈가 2가 맞다면 findAll이 잘 작동하는 것이다.

@Test
    public void findAll() {
        Member member1 = new Member();
        member1.setName("spring1"); // 멤버1에 스프링1
        repository.save(member1); // repo에 저장

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        // 2개의 회원가입

        List<Member> result = repository.findAll();

        assertThat(result.size()).isEqualTo(2); // result 의 총 개수가 2개가 맞는지 확인
    }

💡 테스트 코드 작성 시 유의할 점

위에서 각자의 메서드들의 테스트 할 때는 각각의 메서드를 테스트했다.
하지만 테스트 코드의 장점 중 하나는 여러개의 코드를 동시에 테스트 할 수 있는 점이다.

해당 class에 있는 메서드들을 테스트하고 싶다면 클래스 이름 옆에있는 run을 클릭하면 된다.

만약 test 클래스가 여러개라면 package에서 우클릭 후, run 옵션을 누르면 된다.

하지만 테스트 코드를 동시에 실행할 때는 유의할 점이 있다.
위에서 만든 3개의 test 코드를 각각 run 했을때는 모두 성공했지만 3개를 동시에 run 하면 findByName() 부분이 실패하는것을 볼 수 있다.

전체 코드를 동시에 run하게 되면 실행순서가 정해져있지않아 발생하는 문제이다. 이와 같은 문제를 해결하기 위해서는 각 메서드에 테스트가 끝나면 데이터들을 clear 해주어야 한다.

store 객체를 clear 해줘야하기 때문에 MemoryMemberRepository 클래스 내에 아래와 같은 코드를 작성한다.

public void clearStore(){
    store.clear();
}

그 후 MemoryMemberRepositoryTest 클래스에 @AfterEach 어노테이션을 이용하여 각 메소드가 끝날때마 clear 되는 코드를 적어준다.

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


문제없이 작동하는것을 볼 수 있다.

profile
우엉이의 코딩 성장일기💻

0개의 댓글