Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- pointcut
- 알고리즘
- 스프링
- SpringBoot
- transaction
- Proxy
- Greedy
- Exception
- 백준
- db
- jpa
- JPQL
- 스프링 핵심 원리
- Servlet
- springdatajpa
- 그리디
- Thymeleaf
- java
- spring
- 인프런
- QueryDSL
- Android
- 자바
- JDBC
- kotlin
- 스프링 핵심 기능
- Spring Boot
- AOP
- http
- 김영한
Archives
- Today
- Total
개발자되기 프로젝트
회원 도메인 개발 및 테스트 본문
요구사항 및 클래스 다이어 그램은 이전 글 참고
1. Member class
public class Member {
private Long id;
private String name;
private Grade grade;
public Member(Long id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
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;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
2. Grade enum
- enum은 일종의 상수
public enum Grade {
BASIC,
VIP
}
3. MemberRepository Interface
- 다형성을 활용하기 위해 Repository를 Interface 생성
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
4. MemoryMemberRepository class
- MemberRepository의 구현체
- interface에서 선언한 method를 override하여 구현.
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long, Member> store = new HashMap<>();
//실무에서는 동시성 문제로 concurrentHashMap사용
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}
5. MemberService Interface
- 추후에 service가 변경될 수 있기 때문에 다형성을 활용하기 위해 interface로 생성.
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
6. MemberServiceImpl class
- MemberService interface에 대한 구현체
- 선언된 method를 override하여 구현.
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
7. Test
1) MemberApp class
- 작성한 코드가 실제로 잘 동작하는지 test를 해보자
- test를 위해 MemberApp class를 만들었다.
- 신규 회원을 생성하고 메모리에 저장한다
- findMember로 다시 검색한 결과와 생성한 회원의 이름이 일치하는지 확인하자.
public class MemberApp {
public static void main(String[] args) {
MemberService memberService = new MemberServiceImpl();
Member member = new Member(1L, "A", Grade.VIP);
memberService.join(member);
Member findMember = memberService.findMember(1L);
System.out.println("new Member = " + member.getName());
System.out.println("findMember = " + findMember.getName());
}
}
결과가 잘 나오긴 하지만, main 메서드로 매 번 테스트 하는 것은 바람직 하지 않다.
new Member = A
findMember = A
2) Junit을 활용하여 test 코드 작성
- test코드를 작성시 given, when, then으로 구분하여 작성하면
- 누가봐도 이해하기 쉽고 명확하다.
- Assertions를 사용하면 일일히 프린트를 찍지 않고 결과를 에상 값과 비교할 수 있다.
class MemberServiceTest {
MemberService memberService = new MemberServiceImpl();
@Test
void join(){
//given
Member member = new Member(1L, "memberA", Grade.VIP);
//when
memberService.join(member);
Member findMember = memberService.findMember(1L);
//then
Assertions.assertThat(member).isEqualTo(findMember);
}
}
- test가 실패하면 아래와 같이 에러가 발생한다.
8. 현제 도메인 설계의 문제점
- 저장소를 변경하다고 생각해 보자.
- 현재 service 구현체에서 MemeryMemberRepository를 의존하고 있다.
- 따라서 저장소를 변경 할 경우 Service의 코드까지 변경해야 한다.
- 즉, 저장소를 변경하면 client에 영향을 미친다. - OCP, DIP를 잘 지키고 있나?
- DIP : interface에 의존해야 하는데 구현체에 의존하고 있다. 못지치고 있다
- OCP : 확장하기 위해서는 변경이 필요하다. 못지키고 있다. - 문제는 의존관계가 인터페이스 만 아니라 구현까지 모두 의존하고 있는 것이다.
9. GitHub : 210725, Junit
'인프런 > [인프런] Spring 핵심원리 이해' 카테고리의 다른 글
새로운 할인 정책 개발 (0) | 2021.07.25 |
---|---|
주문, 할인 도메인 개발 & Test (0) | 2021.07.25 |
주문, 할인 도메인 설계 (0) | 2021.07.25 |
회원 도메인 설계 (0) | 2021.07.24 |
비즈니스 요구사항 & 설계 (0) | 2021.07.24 |
Comments