이 글은 김영한님 스프링-입문 강의를 듣고 작성합니다.
[3. 회원 관리 예제 - 백엔드 개발] 강의에 해당된 내용을 정리합니다.
테스트 케이스란?
구현한 기능이 제대로 작동 되는지 확인하기 위해서 main 메서드를 통해서 실행하거나, 웹 애플리케이션의 컨트롤러를 통해 해당 기능을 실행한다. 하지만 이런 방법은 실행하는데 오래 걸리고, 실행되고 데이터를 하나씩 다 입력해야 하고 불편하는 단점이 있다.
Java는 JUnit이라는 프레임워크로 테스트를 실행해서 해당 부분 기능이 잘 동작되는지 확인 할 수 있다!
MemoryMemberRepository 에서 Member domain 객체를 저장하고 관리하는 기능이 잘 되는지 확인해보자!
테스트 케이스 작성
package hello.hellospring.repository;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import hello.hellospring.domain.Member;
import java.util.List;
import org.junit.jupiter.api.Test;
public class MemoryMemberRepositoryTest {
MemberRepository 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));
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);
}
}
각 함수마다 테스트를 실행하면 잘 작동되지만, 전체 클래스를 실행하면 오류가 생긴다.
문제 해결
- 테스트를 전체 실행을 하면 함수 실행 순서를 보장할 수 없다. → 뒤죽박죽
- save() 함수부터 작성했는데 findByName() 함수가 먼저 실행될 수도 있다.
- save() 함수가 먼저 실행되지 않고, findByName() 함수가 먼저 실행이 되면 "spring1" member를 찾을 수 없어 오류가 난다.
- test 하나 끝나고 나면 데이터를 초기화 해줘야한다. ➩ @AfterEach
@AfterEach
@AfterEach
public void afterEach(){
repository.clearStore();
}
- @AfterEach 를 선언함으로써 각 함수가 끝날 때마다 이 함수를 실행.
- 이 함수는 메모리 DB에 저장된 데이터를 삭제한다.
- 하나의 테스트가 끝날 때마다 공용 데이터를 깔끔하게 정리해줘야 한다.
- 테스트는 각각 독립적으로 실행되어야 한다. 테스트 순서에 의존관계가 있는 것은 좋은 테스트가 아니다.
더 좋은 코드 DI
기존 MemberService 클래스에서 MemoryMemberRepository를 새로 생성하고, MemberService 클래스에서도 MemberService, MemoryMemberRepository를 생성하여 사용한다.
public class MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
}
class MemberServiceTest {
MemberService memberService = new MemberService();
MemoryMemberRepository memberRepository = new MemoryMemberRepository();
}
하지만!
MemberService 클래스에서 선언한 MemberRepository랑
MemberServiceTest 클래스에서 선언한 MemberRepository가 서로 다르다.
이는 각자 새로운 리포지토리를 생성해서 실행하는건데, 같은 리포지토리로 테스트가 제대로 이루어졌는지 확인 하기 힘들다.
해결 방법 - @BeforeEach
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
MemberService 클래스에서는 외부에서 유입해주는 걸로. (DI)
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach // 각 테스트를 실행하기 전에
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
MemberServiceTest 클래스에서는 @BeforeEach 을 선언하여 각 테스트를 실행하기 전에 beforeEach() 함수를 실행시키라고 한다.
beforeEach 함수는 memberService 와 memberRepository를 설정한다.
Intellj 편한 단축키
단축키 Command+Shfit+T
Intellj에서 클래스 이름을 선택하고 Command+Shift+T 단축키를 사용하면 자동으로 테스트 케이스 생성해준다.
단축키 Command+option+v
Command+ option + v 를 사용하면 선택한 표현식을 새로운 변수에 넣어준다.
repository.findById(member.getId()).get();
Member member1 = repository.findById(member.getId()).get();
'Spring' 카테고리의 다른 글
@ModelAttribute 언제 사용할까? (0) | 2025.03.24 |
---|---|
HTTP 상태코드에 대해 설명해주세요. (0) | 2024.08.29 |
[Spring] MVC 템플릿 & API 응답 (5) | 2024.08.09 |