

domain 패키지 생성 > hello.hellospring.domaindomain 패키지 아래 Member 클래스 생성public class Member {
private Long id; // id 식별자(시스템이 저장하는 id)
private String name; // 이름
// cmd+N : Getter and Setter 생성
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
repository 패키지 생성 > hello.hellospring.repositoryrepository 패키지 아래 MemberRepository 인터페이스 생성public interface MemberRepository {
Member save(Member member); // 멤버 저장
Optional<Member> findById(Long id); // id로 멤버찾기
Optional<Member> findByName(String name); // 이름으로 멤버찾기
List<Member> findAll(); // 지금까지 저장된 모든 회원 리스트 반환
}
repository 패키지 아래, 구현체 MemoryMemberRepository클래스 생성// implements MemberRepository > opt+enter > Implement methods > 전부 선택 후 ok
public class MemoryMemberRepository implements MemberRepository{
// 저장소 만들기 : 이후 ctrl+space나 option+enter로 import
// 실무에서는 동시성 문제가 있을 수 있어서 이렇게 공유되는 변수일 때는 concurrent HashMap을 써야하지만, 예제니까 단순하게 HashMap 사용
private static Map<Long, Member> store = new HashMap<>();
// Sequence(0,1,2와 같이 키 값을 생성해줌) 만들기 :
// 실무에서는 Atomic Long 등등을 해야하지만 예제이므로 단순하게 구현
private static long sequence = 0L;
@Override
public Member save(Member member) {
// sequence값 증가 후 member의 id로 자동 저장, store 저장소에 저장.
member.setId(++sequence); // 증가 후 저장
store.put(member.getId(),member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
// null값이 나올 가능성이 있는 변수를 Optional.ofNullable로 감싸서 반환
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name)) // member의 name이 파라미터로 넘어온 name과 같은지 확인
.findAny(); // 하나라도 찾으면 그 결과를 그대로 반환 (return값 Optional 설정)
}
@Override
public List<Member> findAll() {
// store은 Map인데 반환은 List로 설정(자바 실무에서 리스트를 많이 쓰기 때문)
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
보통의 테스트 방법 : main 메소드를 통해서 실행/웹 애플리케이션의 컨트롤러를 통해서 실행
-> 준비하고 실행하는데 오래 걸리고, 반복해서 실행하기 어렵고, 여러 테스트를 한 번에 실행하기 어렵다는 단점 !
자바는 JUnit 이라는 프레임워크로 테스트를 실행해서 이러한 문제를 해결한다.
repository 패키지 생성 (보통 똑같으 패키지 이름으로 생성)MemoryMemberRepositoryTest 클래스 생성package hello.hellospring.repository;
import hello.hellospring.domain.Member;
//import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.*;
class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach // 메소드가 실행이 끝날 때마다 동작
public void afterEach(){
repository.clearStore();
}
@Test // @Test를 붙이면 바로 메소드 실행 가능
public void save(){
Member member = new Member();
member.setName("spring");
// member 저장
repository.save(member);
// findById의 반환타입 : Optional
// Optional에서 값을 꺼낼 때는 get 메소드 활용
Member result = repository.findById(member.getId()).get();
// System.out.println("result = "+(result ==member));
// 이렇게 직접 출력하는 방식보다 Assert를 주로 사용함
// org.junit.jupiter.api
// Assertions.assertEquals(member, result); // (expected, actual)
// org.assertj.core.api : 요즘에 더 자주 사용
// Assert에 커서를 두고 opt+ontion > Add on-demand static import를 클릭하면 다음부터는 아래와 같이 assertThat으로 바로 사용 가능
// 실무에서는 Build 툴이랑 엮어서 오류 테스트 케이스를 통과하지 않으면 다음 단계로 못 넘어가게 막아버림.
assertThat(member).isEqualTo(result);
}
@Test
public void findByName(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
// Shift+F6 : rename 단축키
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);
}
}
클래스 레벨에서 돌리거나 좌측 폴더에서 테스트를 하면 전체 클래스를 다 테스트 해 볼 수 있음.
💡테스트는 각각 독립적으로 실행되어야 한다.
💡테스트 순서에 의존관계가 있는 것은 좋은 테스트가 아니다.
@AfterEach. 각 테스트가 종료될 때마다 기능이 실행된다.실습 방법은 구현클래스를 먼저 만들고 테스트 클래스를 작성하는 방식으로 이루어졌으나, 테스트 클래스를 먼저 작성 후, 구현 클래스를 작성하는 방법도 있다. 이 방법을 테스트 주도 개발, TDD라고 한다.