Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

회원 도메인, Repository 만들기 본문

Spring Boot

회원 도메인, Repository 만들기

Seung__ 2021. 7. 22. 11:29

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에 대한 내용은 아래 글 참고

 

Map, HashMap

1. Map  Map은 key & value를 mapping할수 있도록 하는 interface이다. Type parameters: – the type of keys maintained by this map – the type of mapped values public interface Map { Map에서 제공하는 m..

bsh-developer.tistory.com

 

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를 진행해 볼 것이당.

 

Junit-1

Junit이란? 자바용 단위 테스트 도구! * TDD(Test-driven Development) 테스트 주도 개발에서 사용하지만, 코드의 유지 보수 및 운영 환경에서의 에러를 미리 방지하기 위해서 다누이 별로 검증하는 테스트

bsh-developer.tistory.com

 

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


 

 

GitHub - bsh6463/SpringBootClass

Contribute to bsh6463/SpringBootClass development by creating an account on GitHub.

github.com

 

'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
Comments