일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Spring Boot
- java
- Exception
- pointcut
- kotlin
- transaction
- JPQL
- 스프링 핵심 기능
- 그리디
- 백준
- 김영한
- Greedy
- http
- 알고리즘
- Android
- JDBC
- 스프링
- db
- jpa
- 자바
- spring
- Thymeleaf
- SpringBoot
- AOP
- Servlet
- 스프링 핵심 원리
- springdatajpa
- Proxy
- QueryDSL
- 인프런
- Today
- Total
개발자되기 프로젝트
회원 도메인, Repository 만들기 본문
1. Member class
@Data
public class Member {
private Long id;
private String name;
}
2. MemberRepository Interface
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
JPA를 사용하면 위의 코드처럼 선언만 해줘도 사용이 가능하다.
하지만, 지금은 JPA를 사용하지 않기 때문에 해당 method를 사용하기 위해서는
interface에 대한 구현체가 필요하다.
3. MemoryMemberRepository Class
간단하게 memory DB를 구현하기 위해 Map을 사용해 보자.
Map, HashMap에 대한 내용은 아래 글 참고
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L; //0 1 2 key값 생성
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
//null이 반환되면 어쩌지? Optional로 감싼다.
//Optional로 감싸서 return하면 client에서 조치를 취할 수 있다
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());
}
}
4. Test class 작성
JUnit5를 사용하여 Test를 진행해 볼 것이당.
main 메서드를 통해 실행하거나, 웹 애플리케이션의 컨트롤러를 통해 실행할 수 있지만, 오래걸리고 여러 테스트를 한 번에 실행하기 어려운점 등 여러 단점이 있다. JUnit 프레임워크를 사용하면 여러 문제점들을 해결이 가능하다!
윈도우의 경우 test를 작성하고 싶은 파일에서 Ctrtl +Shift + T를 누르면 간단하게 Test class를 생성할 수 있다.
1) save, findbyId test
class MemoryMemberRepositoryTest {
MemoryMemberRepository memoryMemberRepository = new MemoryMemberRepository();
@Test
public void saveTest(){
Member member = new Member();
member.setName("야호");
memoryMemberRepository.save(member);
Member result = memoryMemberRepository.findById(member.getId()).get();
Assertions.assertEquals(member, result);
}
}
위의 테스트의 목적은, 새로 생성한 member와 repository에 저장된 객체가 일치하는지 확인하는 것이다.
Assersions.assertEquals를 활용하면 쉽게 확인이 가능하다.
해당 메서드는 expected와, actual이 같은지! 비교한다.
assertEquals(Object expected, Object actual)
테스트 결과 두 객체가 일치하는 것을 확인했다.
또 다른 방법은 assertj에서 제공하는 Asersions활용이다.
assertj에서 제공하는 Assertions은 해당 기능을 좀더 사용하게 쉽게 만들어져 있다.
요렇게 사용이 가능하다!
Member result = memoryMemberRepository.findById(member.getId()).get();
Assertions.assertThat(member).isEqualTo(result);
추가로 아래와 같이 import시키면 바로 assertThat사용 가능하다.
import static org.assertj.core.api.Assertions.*;
2) findByName Test
@Test
public void findByNameTest(){
Member member1 = new Member();
member1.setName("spring1");
memoryMemberRepository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
memoryMemberRepository.save(member2);
Member result = memoryMemberRepository.findByName("spring1").get();
assertThat(result).isEqualTo(member1);
}
3) Test의 좋은 점은 여러 Test를 같이 돌릴 수 있다는 것이다.
4)findAll
@Test
public void findAllTest(){
Member member1 = new Member();
member1.setName("spring1");
memoryMemberRepository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
memoryMemberRepository.save(member2);
List<Member> result = memoryMemberRepository.findAll();
assertThat(result.size()).isEqualTo(2);
}
5) Test전체 실행
Test 전체를 실행했더니 에러가 발생했다??왜??
로그내용을 보면 실제 repository에 저장된 member의 수가 5이다.
expected: 2
but was : 5
org.opentest4j.AssertionFailedError:
expected: 2
but was : 5 at
전체 test가 순서대로 실행되었으면, 5번 save을 하고 findAll을 하기 때문에 맞는 말인데..
findAllTest는 두 번째에 실행되었고, 따라서 size는 3이어야 말이되는데..?
!!!!!!주의점!!!!!!!
- Test 순서는 보장이 안된다!
- 모든 Test는 순서에 관계 없이 method별로 따로 동작하도록 설계해야 한다.
- 따라서 각 Test가 끝난 후 clear를 해주자.
- repository.clear();
6) 각 Test는 순서에 관계없어야 한다. 저장소, 공용 data를 깔끔하게 지워야 한다.
repository 구현체에 아래와같이 Map을 clear하는 method를 추가하자.
public void clearStore(){
store.clear();
}
그리고 Test에서 아래와 같이 afterEach라는 메서드를 만들고 @AfterEach annotation을 붙여주자.
@AfterEach //각 method실행 끝날대마다 실행
public void afterEach(){
memoryMemberRepository.clearStore();
}
@AfterEach : 각 메서드의 실행이 끝난 후 해당 annotaion이 붙은 메서드가 실행하도록 함.
다시 실행한 결과 깔끔하다.
5. TDD란?
지금의 방법은 먼저 memorymemberRepository를 개발하고 Test를 작성함
반대로 Testclass를 작성 후 MemoryMemberRepository를 개발할 수 있다.
즉, 검증할 수 있는 틀을 먼저 만든 후! 개발! --> TDD( Test Driven Development)라고함.
6. GitHub : 210722, repository, test
'Spring Boot' 카테고리의 다른 글
Spring Bean과 의존관계(@Component 스캔) (0) | 2021.07.22 |
---|---|
회원 서비스 개발 & Test (0) | 2021.07.22 |
비즈니스 요구 사항 정리 (0) | 2021.07.22 |
스프링 웹 개발 기초 (0) | 2021.07.21 |
view 환경설정 (0) | 2021.07.21 |