회원 도메인과 리포지토리 만들기, 테스트케이스 작성

최대환·2022년 8월 14일
0

스프링

목록 보기
4/6

가정

  • 아직 데이터 저장소가 정되지 않아서, 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계
  • 데이터 저장소는 RDB, NoSQL 등등 다양한 저장소를 고민중인 상황으로 가정
  • 개발을 진행하기 위해서 초기 개발 단계에서는 구현체로 가벼운 메모리 기반의 데이터 저장소 사용

회원도메인, 레파지토리 만들기

회원 도메인

우선 아이디와 회원이름만 들어가는 도메인을 설계해보자
Long으로 id를, string타입으로 name을 만들고, 게터세터를 만들어준다.
게터와 세터는 OOP의 특징중 하나로써 다른 클래스에서 직접적으로 현재 클래스의 변수를 다룰수 없게 만들어준다.
예를들어 이름을 입력하는칸에 특수문자를 입력하면 이를 세터에서 입력을 안한걸로 처리한다든지 해서 문제가 생기지 않도록 한다.

domain/Member.java

package hello.hellospring.domain;

public class Member {

    private Long id;
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
}

회원 레파지토리 인터페이스

인터페이스란 통일된 어떠한 형식을 말한다.
그니까 축구에서 감독이 선수가 필요하다며 스카우터보고 선수를 찾아보라고 하면 A스카우터는 골키퍼를, B스카우터는 나이많은 베테랑 수비수를, C 스카우터는 한참 전성기인 공격수를, D 스카우터는 나이어린 미드필더를 추천할 수 도 있다.
하지만 만약 감독이 '왼쪽 윙포워드가 주포지션이고 스피드가 빠른 나이어린 선수' 이렇게 하면 특정 형식에 맞게 스카우터들이 선수를 찾아온다.
이런식으로 어떠한 통일된 형식을 강제하는게 인터페이스이다.
코드로 따지면 MemberRepository는 파라미터로 특정값을 받는 save, findById, findByName, findAll같은게 된다.

repository/MemberRepository.java

package hello.hellospring.repository;

import hello.hellospring.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();
}

회원 레파지토리 메모리 구현체

아래와 같이 인터페이스를 구현했다.
ofNullablenull값을 허용한다는 말이다.

repository/MemoryMemberRepository.java

package hello.hellospring.repository;

import hello.hellospring.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) {
        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());
    }

    public void clearStore() {
        store.clear();
    }
}

회원 리포지토리 테스트 케이스 작성

개발을 했으면 테스트를 해야한다.
아래코드들은 src/text/java 하위 폴더에 생성했다.
이렇게 개발을 하고 테스트코드를 짤 수도 있고 반대로 테스트 코드먼저 짜고 그다음 개발을 하는 경우도 있다. 이걸 TDD(테스트 주도 개발)이라고 하는데 나도 나중에 경험해보고 싶다.


여기서 @AfterEach는 각각의 독립적인 테스트가 끝나고 실행되는 메소드이다.
테스트가 끝나고 난뒤 레파지토리에 저장된 유저정보를 초기화하고 다시 다른 독립적인 테스틀 진행한다.
테스트코드를 작성할때는 절대 의존적이게 짜면안되고 독립적이어야한다.
junit이나 assertj을 사용하면 보다 쉽게 테스트코드를 짤 수 있다.
given-when-then패턴을 테스트 코드 스타일중 하나이다.
given: 테스트 하기 위해 기본적으로 세팅하는 값
when: 테스트를 하기 위한 조건을 지정
then: 테스트 하기 위한 행위가 우리가 예상하는대로 동작하는지 검증하는 행동/절차

repository/MemoryMemberRepositoryTest.java

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;

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


public class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();

    @AfterEach
    public void afterEach() {
        repository.clearStore();
    }
    @Test
    public void save() {
        //given
        Member member = new Member();
        member.setName("sterling");

        //when
        repository.save(member);

        //then
        Member result = repository.findById(member.getId()).get();
        assertThat(member).isEqualTo(result);
    }

    @Test
    public void findByName() {
        //given
        Member member1 = new Member();
        member1.setName("haaland");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("jesus");
        repository.save(member2);

        //when
        Member result = repository.findByName("haaland").get();

        //then
        assertThat(result).isEqualTo(member1);
    }

    @Test
    public void findAll() {
    	//given
        Member member1 = new Member();
        member1.setName("haaland");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("jesus");
        repository.save(member2);

		//when
        List<Member> result = repository.findAll();
		
        //then
        assertThat(result.size()).isEqualTo(2);
    }
}

참고자료

profile
나의 개발지식 output 공간

0개의 댓글