스프링 부트/스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

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

sungw00 2023. 3. 7. 22:24
728x90

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

 

1. test/java/hello.hellospring.repository 패키지 생성, MemoryMemberRepositoryTest 클래스 파일 작성

package hello.hellospring.repository;

import org.junit.jupiter.api.Test;

class MemoryMemberRepositoryTest {
    MemberRepository repository = new MemoryMemberRepository(); // MemoryMemberRepository 객체 생성

    @Test
    public void save() { // save 기능 테스트

    }
}

실행 버튼 클릭하여 save 메서드 실행하여 초록색 체크 표시가 뜬다면 실행이 잘 되는 것

 

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.junit.jupiter.api.Test;

class MemoryMemberRepositoryTest {
    MemberRepository repository = new MemoryMemberRepository(); // MemoryMemberRepository 객체 생성

    @Test
    public void save() { // save 기능 테스트
        Member member = new Member();
        member.setName("spring"); // 이름 저장

        repository.save(member); // repository에 member 객체를 save

        Member result = repository.findById(member.getId()).get(); // ID를 정상적으로 가지고 오는 지 확인
        System.out.println("result = " + (result == member));
    }
}

실행하면 초록색 체크 표시가 나타나고, result = true라는 결과가 나옴으로써 ID를 정상적으로 가지고 오는 것을 확인할 수 있다.

 

하지만 이런식으로 하나하나 확인할 수는 없기에 assert라는 기능이 존재한다.

방금 작성한 코드의 마지막 줄인 System.out.println("result = " + (result == member)); 부분을 아래 코드로 대치한다.

        Assertions.assertEquals(member, result);

Assertions.assertEquals 메서드는 기댓값, 결괏값 순으로 인자를 전달받고 같으면 정상동작, 다르면 오류를 반환한다.

아래는 정상동작하는 경우이다.

 

하지만 정상적으로 동작되었는지 출력되는 것은 없는데, 만약 정상적으로 동작되지 않았다면 다음과 같이 나타난다.

결괏값에 null을 넣게되면 기댓값과 다르게 되어 좌측 로그에는 X 표시와 함께 우측 로그에는 에러가 출력되는 것을 확인할 수 있다.

 

Assertions.assertThat() 메서드를 사용하는 방법

마지막 줄의 Assertions.assertEquals(member, result); 를 다음 코드로 대치한다.

Assertions.assertThat(member).isEqualTo(result);

member가 result와 같은 지 확인하는데 맞으면 아래와 같이 출력된다.

아니라면 아래처럼 에러가 출력된다.


다음으로는 findByName 메서드를 테스트해보자.

findByName( ) 테스트 메서드 코드 작성

@Test
    public void findByName() { // 이름으로 검색하는 메서드
        Member member1 = new Member(); // member1 생성
        member1.setName("spring1"); // name을 spring1로 set
        repository.save(member1); // member1 저장

        Member member2 = new Member(); // member1 생성
        member2.setName("spring2"); // name을 spring2로 set
        repository.save(member2); // member2 저장

        Member result = repository.findByName("spring1").get(); // name이 spring1인 객체를 검색

        assertThat(result).isEqualTo(member1);
    }

결과로 잘 가져옴

 

이번에는 코드를 아래와 같이 수정하고 실행해본다.

@Test
    public void findByName() { // 이름으로 검색하는 메서드
        Member member1 = new Member(); // member1 생성
        member1.setName("spring1"); // name을 spring1로 set
        repository.save(member1); // member1 저장

        Member member2 = new Member(); // member1 생성
        member2.setName("spring2"); // name을 spring2로 set
        repository.save(member2); // member2 저장

        // Member result = repository.findByName("spring1").get();
        Member result = repository.findByName("spring2").get(); // name이 spring2인 객체를 검색 

        // assertThat(result).isEqualTo(member1);
        assertThat(result).isEqualTo(member1);
    }

다른 객체이기때문에 오류가 발생하는 것을 확인할 수 있다.

 

그리고 아래처럼 클래스를 선택한 후 Run을 하면 클래스 전체를 테스트할 수 있다.


findAll 메서드 테스트하기

finaAll 메서드 테스트 코드 추가

@Test
    public void findAll() { //
        Member member1 = new Member(); // member1 객체 생성
        member1.setName("spring1"); // member1의 name을 spring1로 set
        repository.save(member1); // member1 저장

        Member member2 = new Member(); // member2 객체 생성
        member2.setName("spring2"); // member2의 name을 spring2로 set
        repository.save(member2); // member2 저장

        List<Member> result = repository.findAll(); // 결과를 List로 저장

        assertThat(result.size()).isEqualTo(3);
    }

테스트 실행 결과

isEqualsTo의 인자로 3을 넣게되면 아래와 같이 오류가 출력된다.(기대값은 2인데 3과 비교했기 때문)

테스트는 서로 순서에 의존관계 없이 설계되어야 한다. 아래 오류를 보자.

 

findAll() 메서드가 먼저 실행되어 spring1과 spring2가 먼저 저장이 되었고, 이후에 findByName() 메서드가 실행이 될 때는 이미 저장된 객체와는 다른 객체이기때문에 오류가 발생

이 문제를 해결하기 위해 테스트가 끝날때마다 repository를 깔끔하게 지워주는 코드를 작성

 

MemoryMemberRepository.java 클래스에 다음 코드를 추가

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

MemoryMemberRepositoryTest.java 클래스에 다음 코드를 추가

	...
    @AfterEach
    public void afterEach() {
        repository.clearStore(); // 테스트가 실행되고 끝날때마다 저장소를 지움
    }
    ...

이후 다시 클래스를 실행시켜보면 테스트가 잘 되는 것을 확인할 수 있다.

 

이와같이 MemoryMemberRepository를 먼저 개발하고 테스트 클래스를 작성하는 방법이 있고, 반대로 테스트 클래스를 먼저 작성한 후에 MemoryMemberRepository를 작성하는 방법을 TDD(Test Driven Development, 테스트 주도 개발)라고 한다.

728x90