간단한 회원 레포지토리 작성을 위해 인터페이스와 구현체 코드를 작성해준다.
< 회원 레포지토리 인터페이스 >
package Hello.HelloBus.repository;
import Hello.HelloBus.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
< 회원 레포지토리 인터페이스에 대한 구현체 >
package Hello.HelloBus.repository;
import Hello.HelloBus.domain.Member;
import java.util.*;
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) {
// id로 얻는 것인데 만약 존재하지 않는 경우 Null을 반환
// 따라서 Optional로 반환
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());
}
}
HashMap을 통해 회원 아이디와 Member객체를 저장해주고 id를 결정해주는 건 sequence변수를 통해 저장해준다.
인터페이스에 대한 구조체이므로 모든 method는 Override로 작성한다.
☞ findById method를 보면 반환값이 Optional.ofNullable인데 이는 존재하지 않는 id로 HashMap을 조회할 경우 Null값을 반환한다. Null로 반환하는 경우를 대비해 자바의 Optional 객체로 Null값 반환도 가능하게 해주는 방법이다.
☞ findByName method는 람다식을 통해 HashMap에 존재하는 values들을 매개변수 name과 비교하여 찾는 method이다.
☞ findAll() method는 list형태로 HashMap에 존재하는 모든 values를 반환해준다.
이렇게 간단한 인터페이스와 구현체를 만든 후 문제 없이 잘 작성되었는지 test를 위해 TestCase작성을 통해 확인과정을 거쳐준다
package Hello.HelloBus.repository;
import Hello.HelloBus.domain.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
public class MemoryMemberRepositoryTest {
MemoryMemberRepository repository = new MemoryMemberRepository();
@Test
public void save(){
Member member = new Member();
member.setName("spirng");
repository.save(member);
Member result = repository.findById(member.getId()).get();
//Assertions.assertEquals(result, member);
assertThat(member).isEqualTo(result);
}
@Test
public void findByName(){
Member member1 = new Member();
member1.setName("Kim");
repository.save(member1);
Member member2 = new Member();
member2.setName("Park");
repository.save(member2);
Member result = repository.findByName("Kim").get();
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll(){
Member member1 = new Member();
member1.setName("Kim");
repository.save(member1);
Member member2 = new Member();
member2.setName("Park");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
TestCase 작성을 통해 구현한 Repository 인터페이스와 클래스에 오류가 있는지 없는지 확인한다.
다른 것은 어렵지 않게 이해할 수 있는데 asserThat(___).isEqualTo(___) 이게 뭘까?
이는 우리가 생성한 객체를 저장한 후 Repository에서 각각의 방법들을 통해 조회했을 경우 일치하는 객체인지 확인하는 코드이다. 물론 System.out.println(True / False)를 통해 확인할 수 있지만 그렇게 할 경우 출력을 확인해야한다. 하지만
위처럼 assert함수를 이용할 경우 실행 결과를 통해 즉시 알 수 있다.
위 method를 하나씩 실행시켜보면 문제없이 잘 실행된다. 하지만 전체 Test클래스를 한 번에 실행시킬 경우는? 오류가 발생한다. 이유는 method가 하나 실행된 후 method를 통해 repository 객체에 저장한 데이터가 충돌이 일어나기 때문이다. 이를 방지하기 위해서 method각각이 실행된 후 데이터를 클리어시켜주어야한다.
① repository클래스 내에 클리어 method를 하나 만들어준다.
public void clearStore(){
store.clear();
}
② Test클래스 내에 AfterEach 어노테이션을 이용하여 method 실행이 끝날 때마다 repository를 클리어시켜준다.
@AfterEach
public void afterEach(){
repository.clearStore();
}
이렇게 하면 간단한 테스트 케이스 코드 작성도 모두 끝난다.
'Spring > Spring Core Basic' 카테고리의 다른 글
좋은 객체 지향 프로그래밍 (0) | 2022.01.21 |
---|---|
자바 코드로 직접 스프링 빈 등록하기 (0) | 2022.01.06 |
컴포넌트 스캔과 자동 의존관계 설정 (0) | 2022.01.06 |
회원 서비스 테스트 (0) | 2022.01.05 |
회원 서비스 개발 (회원 가입, 회원 조회) (0) | 2022.01.05 |