You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
데이터 : 회원ID, 이름
기능 : 회원 등록, 조회
아직 데이터 저장소가 선정되지 않았다고 가정
일반적인 웹 어플리케이션 계층 구조
컨트롤러 : 웹MVC의 컨트롤러 역할
서비스 : 핵심 비즈니스 로직 구현 (ex. 회원은 중복 가입이 안됨)
리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
도메인 : 비즈니스 도메인 객체 (ex. 회원 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨)
클래스 의존관계
아직 데이터 저장소가 선정되지 않아서, 인터페이스로 구현 클래스를 변경할 수 있도록 설계
데이터 저장소는 RDB, NoSQL 등등 다양한 저장소를 고민중인 상황으로 가정
개발을 진행하기 위해서 초기 개발 단계에서는 구현체로 가벼운 메모리 기반의 데이터 저장소 사용
개발한 기능을 테스트할 때 main 메소드를 통해서 실행하거나, 컨트롤러를 통해 실행할 수 있음. 그러나 너무 오래걸리고 반복 실행하기 어려운 문제점이 존재
따라서 자바는 JUnit 이라는 프레임워크로 테스트를 실행해서 이러한 문제를 해결한다.
회원 레포지토리 메모리 구현체 테스트
packagehello.hellospring.repository;
importhello.hellospring.domain.Member;
importorg.junit.jupiter.api.AfterEach;
importorg.junit.jupiter.api.Test;
importjava.util.List;
importstaticorg.assertj.core.api.Assertions.assertThat;
classMemoryMemberRepositoryTest {
MemoryMemberRepositoryrepository = newMemoryMemberRepository();
//test가 끝날때마다 한번씩 지운다. -> 이렇게하면 순서와 크게 상관이 없어진다.@AfterEachpublicvoidafterEach() {
repository.clearStore();
}
@Testpublicvoidsave() { //동작하는지 확인Membermember = newMember();
member.setName("spring");
repository.save(member); //member를 저장하면 id가 자동 셋팅Memberresult = repository.findById(member.getId()).get();
assertThat(member).isEqualTo(result);
}
@TestpublicvoidfindByName() {
//spring1, spring2가 멤버로 가입이 된 것임Membermember1 = newMember();
member1.setName("spring1");
repository.save(member1);
Membermember2 = newMember();
member2.setName("spring2");
repository.save(member2);
Memberresult = repository.findByName("spring1").get(); // spring1을 지금 찾겠다는 의미assertThat(result).isEqualTo(member1);
}
@TestpublicvoidfindAll() {
//findAll이 먼저 실행이 되면, 여기서 spring1과 spring2가 이미 저장이 되어버림// 이런 문제를 해결하기 위해서 테스트가 하나 끝나고 나면 데이터를 클리어 해줘야함Membermember1 = newMember();
member1.setName("spring1");
repository.save(member1);
Membermember2 = newMember();
member2.setName("spring2");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
@AfterEach : 한 번에 여러 테스트를 실행하면 메모리 DB에 직전 테스트 결과가 남을 수 있다. 이럴 경우 다음 테스트가 실패할 가능성이 있다. 따라서 @AfterEach를 사용하면 test가 끝날때마다 한번씩 지워 순서와 크게 상관이 없어진다.
테스트는 각각 독립적으로 실행되어야 한다. 테스트 순서에 의존관계가 있는 것은 좋은 테스트가 아니다.
회원 서비스 개발
packagehello.hellospring.service;
importhello.hellospring.domain.Member;
importhello.hellospring.repository.MemberRepository;
importjava.util.List;
importjava.util.Optional;
publicclassMemberService {
privatefinalMemberRepositorymemberRepository;
publicMemberService(MemberRepositorymemberRepository) {
this.memberRepository = memberRepository;
}
/** * 회원 가입 */publicLongjoin(Membermember) {
//같은 이름이 있는 중복 회원 x//null이 아니라 어떤 값이 있으면 로직이 동작한다. (Optional이라 가능한 일이다.)validateDuplicateMember(member); //중복 회원 검증memberRepository.save(member);
returnmember.getId();
}
privatevoidvalidateDuplicateMember(Membermember) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
thrownewIllegalStateException("이미 존재하는 회원입니다. ");
});
}
/** * 전체 회원 조회 */publicList<Member> findMembers() {
returnmemberRepository.findAll();
}
publicOptional<Member> findOne(LongmemberId) {
returnmemberRepository.findById(memberId);
}
}
서비스는 비지니스에 의존적으로 설계를 하고, 리포지토리는 기계적으로 개발스러운 용어를 선택을 한다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
비즈니스 요구사항 정리
회원 도메인과 리포지토리 만들기
Member ClassMemberRepository InterfaceMemoryMemberRepository회원 리포지토리 테스트 케이스 작성
@AfterEach: 한 번에 여러 테스트를 실행하면 메모리 DB에 직전 테스트 결과가 남을 수 있다. 이럴 경우 다음 테스트가 실패할 가능성이 있다. 따라서@AfterEach를 사용하면 test가 끝날때마다 한번씩 지워 순서와 크게 상관이 없어진다.회원 서비스 개발
회원 서비스 테스트
@BeforeEach: 각 테스트 실행 전에 호출된다. 테스트가 서로 영향이 없도록 항상 새로운 객체를 생성하고, 의존관계도 새로 맺어준다.Beta Was this translation helpful? Give feedback.
All reactions