회원 관리 예시 – 배경 개발

조직의 비즈니스 요구 사항

데이터: 회원ID, 이름
기능
: 가입하기, 확인하다
데이터 저장소를 선택하지 않았습니다.

(가상 시나리오)

일반적인 웹 애플리케이션 계층


컨트롤러: Web MVC에서 컨트롤러의 역할

서비스: 핵심 비즈니스 로직 구현

리포지토리: 데이터베이스에 액세스하고 데이터베이스의 도메인 개체를 저장 및 관리합니다.

도메인: 비즈니스 도메인 객체 예시 멤버십 주문 쿠폰은 주로 데이터베이스에 저장 및 관리됩니다.

클래스 종속성


데이터 저장소가 선택되지 않았기 때문에 먼저 인터페이스를 변경하도록 구현 클래스를 설계하는 것이 매우 편리합니다.

데이터 저장을 위해 RDB 또는 Nosql과 같은 다양한 저장 옵션을 고려하고 있다고 가정합니다.

개발의 경우 초기 개발 단계에서 구현으로 경량 메모리 기반 데이터를 사용합니다.

구성원 도메인 및 리포지토리 생성

패키지 만들기 -> 도메인 클래스 -> 구성원


창고 구성원 인터페이스


멤버쉽


구성원 저장소 테스트 사례 작성

개발된 기능을 실행하고 테스트할 때, 기본 실행 방법

웹 애플리케이션의 컨트롤러를 통해 기능 실행.

이 방법은 준비하고 실행하는 데 오랜 시간이 걸립니다.

, 단점은 반복적으로 실행하기 어렵고 한 번에 여러 테스트를 실행하기 어렵다는 점입니다.

.

자바는 유닛 J라는 프레임워크로 테스트를 실행하여 이러한 문제를 해결합니다.

.

케이스 테스트 저장


테스트를 위해 가맹점에 저장


비어 있는지 테스트하기 위해 가맹점에 저장


조회 이름 테스트


result(member1)와 member1의 값이 같은 객체와 비교되기 때문에 오류가 없습니다.

스프링2라면


result(member2)와 member1의 값이 서로 다른 객체를 비교하고 있어 오류가 발생합니다.

모두


테스트를 계속하면 스프링이 저장되었기 때문에 오류가 발생합니다.

따라서 저장 데이터 테스트를 지워야 합니다.

package oss.board.repository;


import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import oss.board.domain.Member;

import java.util.List;
import java.util.Optional;

import static org.assertj.core.api.Assertions.*;

public class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();
    @AfterEach // 메서드 데스트 데이터를 한개씩 끝나면 실행되며 클리어 해주는  콜백매서드
    public void afterEach(){
    repository.clearStore();
    }
    
    @Test
    public void save(){
    Member member = new Member();
        member.setName("spring");
        repository.save(member);
        Member result = repository.findById(member.getId()).get();
        assertThat(member).isEqualTo(result);


        //System.out.println("result = " + (result == member)); // 내가 새로 만든 것과 db에있느것이 같은지를 확인한다.

//Assertions.assertEquals(member, null); } @Test public void findByName(){ Member member1 = new Member(); member1.setName("Spring1"); repository.save(member1); Member member2 = new Member(); member2.setName("Spring2"); repository.save(member2); //shift+F6 를 쓰면 쉽게 만든다.

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); // 객체를 만들고 조회 했을때 갯수 같으면 통과 다르면 오류난다.

} }

테스트를 먼저 구현한 다음 메인 클래스를 구현하는 것을 TTD 개발이라고 합니다.

회원 서비스 개발

package oss.board.Service;

import oss.board.domain.Member;
import oss.board.repository.MemberRepository;
import oss.board.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {
    private final MemberRepository memberRepository = new MemoryMemberRepository();

    // 회원가입
    //Member member1 = result.get(); 겟으로 해서 직접 뽑아낼 수있지만 권장하지 않는다.

public Long join(Member member){ // 중복되는 이름이 있으면 안된다 validateDuplicateMember(member); // 중복 회원 검증 memberRepository.save(member); return member.getId(); } private void validateDuplicateMember(Member member) { memberRepository.findByName(member.getName()) .ifPresent(member1 -> { throw new IllegalStateException("이미존재하는 회원입니다.

"); }); } // 전체 회원 조회 public List<Member> findMembers(){ return memberRepository.findAll(); } public Optional<Member>findOne(Long memberId){ return memberRepository.findById(memberId); }

회원 서비스 테스트

회원가입


중복 멤버 예외 테스트


널 포인트 예외


데이터 값이 비어 있으면 오류가 발생합니다.


멤버 서비스 클래스의 IllealStateException에 대한 메시지 및 테스트 잘못된 상태 예외 메시지가 다르면 에러가 나니 주의하세요

여기에서도 테스트 중에 오류가 발생할 수 있으므로 깨끗한 메서드를 만들어 보겠습니다.

@AfterEach // 메서드 데스트 데이터를 한개씩 끝나면 실행되며 클리어 해주는  콜백매서드
public void afterEach(){
    memberRepository.clearStore();
}