[스프링부트 입문] 시리즈 #04 회원 리포지토리 만들기 + 테스트

2023. 9. 4. 18:12·Back/Spring(Springboot)

스프링부트 입문 시리즈

#01 프로젝트 생성하기

#02 정적페이지 만들고 화면 띄우기 

#03 회원 관리 페이지 만들기 

#04 회원 리포지토리 만들기 + 테스트 👈


 

1. Test Case

개발한 기능을 테스트할 때 Java의 main 메소드를 통해서 실행하거나,

웹 어플리케이션의 Controller를 통해서 해당 기능을 실행하는데

이런 방법은 준비와 실행이 오래 걸리고, 반복하기 어렵고, 여러 테스트를 한번에 실행하기 어렵다는 단점이 있다

Java는 JUnit이라는 프레임워크를 이용해 이러한 문제를 해결한다

 

 

src / test에 이미 테스트를 할 수 있는 공간이 준비되어있다

 

 

scr / test/ java에 있는 yeon.hello_spring 패키지 안에 repository라는 패키지를 만들고

MemoryMemberRepositoryTest 라는 클래스를 만든다음 그 안에 테스트 코드를 작성하면 된다

 

MemorymemberRepositoy 클래스를 테스트하고 싶은데

테스트하고 싶은 클래스이름 뒤에 Test를 붙이는 것이 관례이다

 

하지만 이렇게 직접 클래스를 일일이 만들지 않고도 Test Case 코드를 작성할 수 있는데

다음과 같은 방법을 사용하면 된다 👉 Test Case 만들기

 

1.1 save() 테스트

 

@Test
void save() {
	Member member = new Member();
	member.setName("soyeon");
	
	repository.save(member);
	
	Member result = repository.findById(member.getId()).get();
	Assertions.assertEquals(member, result);
}

 

member에 이름을 넣고 리포지토리에 저장한 다음

두 개의 값이 같은지 비교하는 테스트이다

 

 

테스트를 실행해 보면 딱히 출력되는 건 없지만 녹색 불이 들어오는 것을 확인할 수 있다

 

 

만약 result 대신 null을 넣어서 테스트해 보면

Assertions.assertEquals(member, null);

빨간불이 들어오면서 아래 에러 메시지를 살펴보면

expected: <yeon.hello_spring.domain.Member@3301500b> but was: <null>

기대했던 값은 Member@3301500b 인데 null이라는 메시지를 확인할 수 있다

 

우리는 방금 test를 할 때

import org.junit.jupiter.api.Assertions;

를 import 해서 사용했지만 요즘에 org.assertj.core.api를 더 많이 쓴다(더 편리하다)

 

org.junit.jupiter

Assertions.assertEquals(member, result);

org.assertj.core.api

Assertions.assertThat(member).isEqualTo(result);

 

 

솔직히 내 눈에는 별차이 없는 거 같고 둘이 걍 비슷비슷해 보이는데

여기에 잘 정리돼 있어서 한번 읽어보면 좋을 것 같다

 

assertj는 static import 해서 간단하게 사용할 수 도 있다

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

assertThat(member).isEqualTo(result);

 

 

assertj를 사용한 코드:)

@Test
void save() {
	Member member = new Member();
	member.setName("soyeon");
		
	repository.save(member);
		
	Member result = repository.findById(member.getId()).get();
	assertThat(member).isEqualTo(result);
}

 

 

1.2 findByName() 테스트

 

@Test
void findByName() {
		
	Member member1 = new Member();
	member1.setName("aaa");
	repository.save(member1);
		
	Member member2 = new Member();
	member2.setName("bbb");
	repository.save(member2);
		
	Member result = repository.findByName("aaa").get();
	assertThat(result).isEqualTo(member1);
}

 

aaa라는 member1과 bbb라는 member2의 값을 받아서

repository에 저장한 뒤

repositoy의 findByName 메소드를 사용해 aaa라는 회원을 찾아 result에 담고

assertThat으로 result의 값과 member1의 값이 같은지를 확인하는 코드이다

 

결과는 당연히 녹색불!

 

 

1.3 findAll() 테스트

 

@Test
void findAll() {
		
	Member member1 = new Member();
	member1.setName("ccc");
	repository.save(member1);
		
	Member member2 = new Member();
	member2.setName("ddd");
	repository.save(member2);
		
	List<Member> result = repository.findAll();
		
	assertThat(result.size()).isEqualTo(2);
		
}

member1과 member2의 값을 받아 repository에 저장한 뒤

findAll()메소드로 저장된 member의 값을 result에 담는다

assertTaht으로 result의 크기(저장된 member의 개수)가 2개 인지 테스트하는 코드

 

녹색불!!

 

이렇게 테스트를 모두 해보았다

 

2. @AfterEach

테스트를 할 때 주의해야할 부분이 있다

MemoryMemberRepositoryTest에는

save(), findByName(), findAll() 이렇게 3개의 테스트 메소드들 있는데

우리가 차례로 메소드를 작성했다고 해서 이 메소드들이 위에서부터 차례로 테스트되는게 아니라

랜덤으로 돌아가기 때문에 값이 중복될 우려가 있다

따라서 테스트 하나가 끝나면 초기화를 해줘야 하는데 이 때 사용되는 것이 AfterEach이다

 

@AfterEach 어노테이션이 명시된 메소드는

각 테스트가 종료될 때 마다 해당 메소드를 호출한다

 

먼저 MemoryMemberRepositoy.java에 맨 밑에 다음 코드를 추가해준다

 

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

 

자바 Map의 clear() 메소드를 사용하면 Map의 전체 내용을 삭제할 수 있다

그 다음 MemoryMemberRepositoyTest로 가서 afterEach()에 clearStore를 호출해준다

 

	@AfterEach
	void afterEach() {
		repository.clearStore();
	}

 

이렇게 하면 테스트 메소드가 종료될 때마다 리포지토리를 지운다

여기까지 MemoryMemberRepositoy에 회원 등록, 검색 기능을 만들고

Test Case를 만들어 제대로 동작하는지까지 테스트 해보았다

 

3. 전체코드

MemoryMemberRepository

package yeon.hello_spring.repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import yeon.hello_spring.domain.Member;

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();
	}
}

 

MemoryMemberRepositoryTest

package yeon.hello_spring.repository;

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

import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import yeon.hello_spring.domain.Member;

class MemoryMemberRepositoryTest {
	
	MemoryMemberRepository repository = new MemoryMemberRepository();
	
	@AfterEach
	void afterEach() {
		repository.clearStore();
	}

	@Test
	void save() {
		Member member = new Member();
		member.setName("soyeon");
		
		repository.save(member);
		
		Member result = repository.findById(member.getId()).get();
		assertThat(member).isEqualTo(result);
	}
	
	@Test
	void findByName() {
		
		Member member1 = new Member();
		member1.setName("aaa");
		repository.save(member1);
		
		Member member2 = new Member();
		member2.setName("bbb");
		repository.save(member2);
		
		Member result = repository.findByName("aaa").get();
		assertThat(result).isEqualTo(member1);
	}
	
	@Test
	void findAll() {
		
		Member member1 = new Member();
		member1.setName("ccc");
		repository.save(member1);
		
		Member member2 = new Member();
		member2.setName("ddd");
		repository.save(member2);
		
		List<Member> result = repository.findAll();
		
		assertThat(result.size()).isEqualTo(2);
		
	}
}

 


스프링부트 입문 시리즈

#01 프로젝트 생성하기

#02 정적페이지 만들고 화면 띄우기 

#03 회원 관리 페이지 만들기 

#04 회원 리포지토리 만들기 + 테스트 👈


 

저작자표시 (새창열림)

'Back > Spring(Springboot)' 카테고리의 다른 글

[스프링부트 입문] 시리즈 #05 회원 서비스 개발 + 테스트  (0) 2023.09.05
[스프링부트 입문] 시리즈 #03 회원 관리 페이지 만들기  (0) 2023.09.01
[스프링부트 입문] 시리즈 #02 정적페이지 만들고 화면 띄우기  (0) 2023.08.31
[스프링부트 입문] 시리즈 #01 프로젝트 생성하기  (0) 2023.08.30
[Spring] 빌드 관리 도구 : Maven과 Gradle의 차이  (0) 2023.08.23
'Back/Spring(Springboot)' 카테고리의 다른 글
  • [스프링부트 입문] 시리즈 #05 회원 서비스 개발 + 테스트
  • [스프링부트 입문] 시리즈 #03 회원 관리 페이지 만들기
  • [스프링부트 입문] 시리즈 #02 정적페이지 만들고 화면 띄우기
  • [스프링부트 입문] 시리즈 #01 프로젝트 생성하기
soyeon26
soyeon26
  • soyeon26
    개발 일지
    soyeon26
  • 전체
    오늘
    어제
    • 분류 전체보기 (107)
      • Web (22)
        • Web (1)
        • HTTP (0)
      • Language (29)
        • Java Script (3)
        • Type Srcipt (1)
        • Java (25)
      • Front (19)
        • HTML+CSS (4)
        • React (15)
      • Back (41)
        • Spring(Springboot) (9)
        • JSP (21)
        • Database (5)
        • NestJS (6)
      • Devops (6)
        • Docker (1)
        • Git & SVN (5)
      • App (7)
        • Android (7)
      • IT 정보 (3)
  • 블로그 메뉴

    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    java의 정석
    과학기술인 등록
    sql강의
    김영한
    SSR
    백엔드
    강의 후기
    csr과ssr의 차이
    프론트엔드
    Next.js 필요성
    데이터베이스 강의
    Java
    과학기술인등록번호 조회
    과학기술인번호 조회
    중복제거
    csrvsssr
    springboot
    Spring
    Next.js
    서블릿
    React Next.js
    인프런
    javascript
    강의후기
    React
    자바스크립트set
    SQL강의 추천
    과학기술인 번호 발급
    과학기술인 등록번호 발급
    스프링부트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
soyeon26
[스프링부트 입문] 시리즈 #04 회원 리포지토리 만들기 + 테스트
상단으로

티스토리툴바