스프링부트 입문 시리즈
#04 회원 리포지토리 만들기 + 테스트 👈
1. Test Case
개발한 기능을 테스트할 때 Java의 main 메소드를 통해서 실행하거나,
웹 어플리케이션의 Controller를 통해서 해당 기능을 실행하는데
이런 방법은 준비와 실행이 오래 걸리고, 반복하기 어렵고, 여러 테스트를 한번에 실행하기 어렵다는 단점이 있다
Java는 JUnit이라는 프레임워크를 이용해 이러한 문제를 해결한다
src / test에 이미 테스트를 할 수 있는 공간이 준비되어있다
scr / test/ java에 있는 yeon.hello_spring 패키지 안에 repository라는 패키지를 만들고
MemoryMemberRepositoryTest 라는 클래스를 만든다음 그 안에 테스트 코드를 작성하면 된다
MemorymemberRepositoy 클래스를 테스트하고 싶은데
테스트하고 싶은 클래스이름 뒤에 Test를 붙이는 것이 관례이다
하지만 이렇게 직접 클래스를 일일이 만들지 않고도 Test Case 코드를 작성할 수 있는데
다음과 같은 방법을 사용하면 된다 👉 Test Case 만들기
1.1 save() 테스트
@Test
void save() {
Member member = new Member();
member.setName("soyeon");
repository.save(member);
Member result = repository.findById(member.getId()).get();
Assertions.assertEquals(member, result);
}
member에 이름을 넣고 리포지토리에 저장한 다음
두 개의 값이 같은지 비교하는 테스트이다
테스트를 실행해 보면 딱히 출력되는 건 없지만 녹색 불이 들어오는 것을 확인할 수 있다
만약 result 대신 null을 넣어서 테스트해 보면
Assertions.assertEquals(member, null);
빨간불이 들어오면서 아래 에러 메시지를 살펴보면
expected: <yeon.hello_spring.domain.Member@3301500b> but was: <null>
기대했던 값은 Member@3301500b 인데 null이라는 메시지를 확인할 수 있다
우리는 방금 test를 할 때
import org.junit.jupiter.api.Assertions;
를 import 해서 사용했지만 요즘에 org.assertj.core.api를 더 많이 쓴다(더 편리하다)
org.junit.jupiter
Assertions.assertEquals(member, result);
org.assertj.core.api
Assertions.assertThat(member).isEqualTo(result);
솔직히 내 눈에는 별차이 없는 거 같고 둘이 걍 비슷비슷해 보이는데
여기에 잘 정리돼 있어서 한번 읽어보면 좋을 것 같다
assertj는 static import 해서 간단하게 사용할 수 도 있다
import static org.assertj.core.api.Assertions.*;
assertThat(member).isEqualTo(result);
assertj를 사용한 코드:)
@Test
void save() {
Member member = new Member();
member.setName("soyeon");
repository.save(member);
Member result = repository.findById(member.getId()).get();
assertThat(member).isEqualTo(result);
}
1.2 findByName() 테스트
@Test
void findByName() {
Member member1 = new Member();
member1.setName("aaa");
repository.save(member1);
Member member2 = new Member();
member2.setName("bbb");
repository.save(member2);
Member result = repository.findByName("aaa").get();
assertThat(result).isEqualTo(member1);
}
aaa라는 member1과 bbb라는 member2의 값을 받아서
repository에 저장한 뒤
repositoy의 findByName 메소드를 사용해 aaa라는 회원을 찾아 result에 담고
assertThat으로 result의 값과 member1의 값이 같은지를 확인하는 코드이다
결과는 당연히 녹색불!
1.3 findAll() 테스트
@Test
void findAll() {
Member member1 = new Member();
member1.setName("ccc");
repository.save(member1);
Member member2 = new Member();
member2.setName("ddd");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
member1과 member2의 값을 받아 repository에 저장한 뒤
findAll()메소드로 저장된 member의 값을 result에 담는다
assertTaht으로 result의 크기(저장된 member의 개수)가 2개 인지 테스트하는 코드
이렇게 테스트를 모두 해보았다
2. @AfterEach
테스트를 할 때 주의해야할 부분이 있다
MemoryMemberRepositoryTest에는
save(), findByName(), findAll() 이렇게 3개의 테스트 메소드들 있는데
우리가 차례로 메소드를 작성했다고 해서 이 메소드들이 위에서부터 차례로 테스트되는게 아니라
랜덤으로 돌아가기 때문에 값이 중복될 우려가 있다
따라서 테스트 하나가 끝나면 초기화를 해줘야 하는데 이 때 사용되는 것이 AfterEach이다
@AfterEach 어노테이션이 명시된 메소드는
각 테스트가 종료될 때 마다 해당 메소드를 호출한다
먼저 MemoryMemberRepositoy.java에 맨 밑에 다음 코드를 추가해준다
public void clearStore() {
store.clear();
}
자바 Map의 clear() 메소드를 사용하면 Map의 전체 내용을 삭제할 수 있다
그 다음 MemoryMemberRepositoyTest로 가서 afterEach()에 clearStore를 호출해준다
@AfterEach
void afterEach() {
repository.clearStore();
}
이렇게 하면 테스트 메소드가 종료될 때마다 리포지토리를 지운다
여기까지 MemoryMemberRepositoy에 회원 등록, 검색 기능을 만들고
Test Case를 만들어 제대로 동작하는지까지 테스트 해보았다
3. 전체코드
MemoryMemberRepository
package yeon.hello_spring.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import yeon.hello_spring.domain.Member;
public class MemoryMemberRepository implements MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream().filter(member -> member.getName().equals(name)).findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
MemoryMemberRepositoryTest
package yeon.hello_spring.repository;
import static org.assertj.core.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import yeon.hello_spring.domain.Member;
class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
void afterEach() {
repository.clearStore();
}
@Test
void save() {
Member member = new Member();
member.setName("soyeon");
repository.save(member);
Member result = repository.findById(member.getId()).get();
assertThat(member).isEqualTo(result);
}
@Test
void findByName() {
Member member1 = new Member();
member1.setName("aaa");
repository.save(member1);
Member member2 = new Member();
member2.setName("bbb");
repository.save(member2);
Member result = repository.findByName("aaa").get();
assertThat(result).isEqualTo(member1);
}
@Test
void findAll() {
Member member1 = new Member();
member1.setName("ccc");
repository.save(member1);
Member member2 = new Member();
member2.setName("ddd");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
스프링부트 입문 시리즈
#04 회원 리포지토리 만들기 + 테스트 👈
'Framework(Library) > Spring(Springboot)' 카테고리의 다른 글
[스프링부트 입문] 시리즈 #05 회원 서비스 개발 + 테스트 (0) | 2023.09.05 |
---|---|
[스프링부트 입문] 시리즈 #03 회원 관리 페이지 만들기 (0) | 2023.09.01 |
[스프링부트 입문] 시리즈 #02 정적페이지 만들고 화면 띄우기 (0) | 2023.08.31 |
[스프링부트 입문] 시리즈 #01 프로젝트 생성하기 (0) | 2023.08.30 |
[Spring] 빌드 관리 도구 : Maven과 Gradle의 차이 (0) | 2023.08.23 |