반응형

MemberRepository TestCode?

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

 

Save 기능 Test

test code 작성할 파일이 repository 패키지에 MemoryMemberRepository이기 때문에 뒤에 Test만 붙여서
test/java에 repository 패키지 생성 -> MemoryMemberRepositoryTest.java를 생성해줍니다.

// MemoryMemberRepositoryTest.java

...

    MemberRepository repository = new MemoryMemberRepository();

    @Test // 테스트 코드 작성을 위한 어노테이션
    public void save() {
    	// save 기능 테스트
        Member member = new Member();
        member.setName("spring");
        // 임의로 spring 이라는 name을 넣어줌
        repository.save(member);
        Member result = repository.findById(member.getId()).get();
        Assertions.assertThat(member).isEqualTo(result);
        // import org.assertj.core.api.Assertions;
        // member와 result 값이 같은지 확인
    }
    
...​

 

Assertions에 블록지정하고 option + Enter 키를 입력하시면 Add on demand static import....이라는 메뉴가 있습니다. 그걸 누르시면 assertThat 만 입력해도 사용이 가능합니다.
2번째 이미지를 보시면 import org.assertj.core.api.Assertions; 이 비활성화되고 import static org.assertj.core.api.Assertions.*; 이 활성화된 걸 보실 수 있습니다. 그렇게 되면 3번째 이미지처럼 Assertions이 사라지고 바로 assertThat 사용이 가능합니다.

add on demand static import for ...
improt static 활성화
assertThat

 

findByName 기능 Test

이름으로 찾는 기능을 테스트 하기 위해서 임의로 이름을 등록해 줍니다.

// MemoryMemberRepositoryTest.java

...

	@Test
    public void findByName() {
        Member member1 = new Member();
        member1.setName("spring1");
        // member1이라고 만들고 거기에 spring1 이라는 이름을 세팅해준다.
        repository.save(member1);
		// 테스트를 위해서 repository에 저장한다.
        
 }
 
 ...

좀 더 확실한 테스트를 위해서 spring2를 만들 건데요 
복사 붙여 넣기 후 이름만 변경 해 주시면 됩니다. 

 

nember1을 블록 지정해서 shift + F6 단축키를 누르시면 이름 변경 기능이 있습니다.
member2라고 이름을 변경하면 밑에 member1이었던 이름이 member2로 변경된 걸 보실 수 있습니다.

이름 변경

그럼 이제 테스트 코드를 입력하겠습니다.
// MemoryMemberRepositoryTest.java

...

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

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

        Member result = repository.findByName("spring1").get();
        assertThat(result).isEqualTo(member1);

    }

...

 

 

findAll() 기능 Test

// MemoryMemberRepositoryTest.java

...

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

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);
        
        // 아까 전과 마찬가지로 2개정도 테스트를 진행해봅니다.

        repository.findAll();

    }


...
마지막 구문에 repository.findAll()까지 작성하고 option + command + V (표현식)를 누르시면 List <Member>로 바뀝니다. 저기서 all을 result 등으로 변경해서 코딩을 하셔도 됩니다.

표현식

// MemoryMemberRepositoryTest.java

...

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

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

        List<Member> result = repository.findAll();
        assertThat(result.size()).isEqualTo(2);
        
        // 2개의 값이 들어있는게 맞는지 확인
    }


...

여기까지 현재 구현한 기능은 모두 테스트를 해 보았습니다.

 

class 실행 시 전체 테스트가 가능하지만 오류가 발생한다?

class를 실행하면 구현한 전체 test 가 실행됩니다.
하나씩 실행했을 때는 제대로 실행이 되었는데 한 번에 실행하니 오류가 발생했습니다.

전체 실행하니 오류 발생?

findAll() Test가 먼저 실행되었기 때문에 이미 값이 들어가 있어서 findByName()이 오류가 발생했습니다.
제대로 실행하려면 변경할 부분이 몇 가지 있습니다.
테스트는 순서와 상관없이(의존관계 없이) 실행될 수 있게 설계가 되어야 합니다.
그러기 위해서는 하나의 테스트가 끝날 때마다 저장소나 공용 데이터들을 깨끗하게 지워줘야 합니다. 그래야 아무런 문제가 없이 잘 실행되는 것을 보실 수 있습니다.
// MemoryMemberRepositoryTest 수정

package repository;

import hellospring.hello.domain.Member;
import hellospring.hello.repository.MemberRepository;
import hellospring.hello.repository.MemoryMemberRepository;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.*;

public class MemoryMemberRepositoryTest {
    MemberRepository repository = new MemoryMemberRepository();
    //!! MemberRepository -> MemoryMemberRepository로 변경
    
    //!! 코드 추가
     @AfterEach
    public void afterEach() {
        repository.clearStore();
    }
    //!! 여기까지 추가
    // 하나의 Test가 끝날 때마다 저장소를 깨끗이 비워줍니다.
    

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

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

        Member member2 = new Member();
        member2.setName("spring2");
        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("spring2");
        repository.save(member2);

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

}​

// MemoryMemberRepository
// 마지막 구문에 추가
...
    public void clearStore() {
        store.clear();
    }
...

// 저장소를 비워주는 코드입니다.

 

수정하니 모두 OK!

TDD (테스트 주도 개발)라고
틀(테스트)을 먼저 만들고 구현 클래스를 만들어서 실행이 잘 되는지 확인해보는 방법도 있습니다.

혼자 아주 소규모의 개발을 할 때를 제외하고는 테스트코드가 없이 개발 하는 것은 불가능하다고 볼 수 있습니다.
테스트코드 관련해서는 정말 깊이 있게 공부하기를 추천합니다.
반응형
복사했습니다!