-정영한님의 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술'로 공부중입니다.
저번 시간에는 도메인과 리포지토리를 완성했었다. 이제 서비스를 구현하고, 구현한 서비스, 도메인, 리포지토리를 테스트해볼 것이다.
제공하는 서비스로는 회원가입, 전체 회원 조회 및, 특정 회원 조회를 제공 할 것이다.
소스코드로 알아보자.
//서비스 패키지에 생성.
import java.util.List;
import java.util.Optional;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/*
* 회원 가입
*/
public Long join(Member member){
//중복 불가
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
public void validateDuplicateMember(Member member){
memberRepository.findByName(member.getName())
.ifPresent(m -> {throw new IllegalStateException("이미 존재하는 회원입니다.");});
}
/*
* 전체 회원 조회
*/
public List<Member> findMembers(){
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId){
return memberRepository.findByID(memberId);
}
}
처음 부분은 리포지토리 클래스를 만들고, 유연한 사용을 위해서 DI를 해준 것이다.
테스트를 실행할 때, 메인 메서드를 통해 실행하거나 웹 애플리케이션의 컨트롤러를 통해 기능을 실험해 볼 수 있다. 하지만 이런 방법은 준비 및 실행이 오래걸리고, 반복적으로 실행하거나 한번에 많은 테스트를 실행하기가 어렵다는 단점이 있다.java에서는 JUnit을 제공해준다. 숨겨진 단위 테스트를 끌어낸 후 정형화하여 단위 테스트를 쉽게 해주는 테스트용 Framework이다.
//src/test/java하위폴더에 repository 패키지를 생성한다.
import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import hello.hellospring.domain.Member;
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();
Assertions.assertThat(member).isEqualTo(result);
}
@Test
public void findByName() {
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
Member result = repository.findByName("spring1").get();
Assertions.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();
Assertions.assertThat(result.size()).isEqualTo(2);
}
}
만들어놓은 MemoryMemberRepository를 생성해준다.
🖐 여기서 assertions을 사용하게 되는데, 가정하고 있는 사실이 올바른 지 검사할 수 있도록 하기 위해서 존재하는 기능이다. assertThat은 타겟을 적은 후, 메서드를 통해 검사하게 된다. 장점으로는 에러 메세지, 실패 메세지가 확인하기 쉽게 나오게 된다. 문제뿐만 아니라 문제가 되는 값을 출력해준다.
소스코드를 실행시켜주면 test result에 잘 실행이 된건지 확인할 수 있다.

우측 아래에 성공과 실패가 나타나게 된다. 실패가 발생한다. 왜냐면 이미 존재하는 값이 문제가 되어 발생하는 것으로, 테스트 실행마다 저장되어있는 값을 비워주어야 한다.
✅ 이를 위해 사용되는 AfterEach라는 이노미테이션이다. 매 테스트마다 repository를 초기화해주고, 다음 테스트를 실행하게 된다. 적힌 소스코드에서 AfterEach부분의 주석처리를 지운다면 잘 실행이 되는 모습을 볼 수 있다.

//src/test/java하위폴더에 service 패키지를 생성한다.
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
public class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository repository;
@BeforeEach
public void BeforeEach() {
repository = new MemoryMemberRepository();
memberService = new MemberService(repository);
}
@AfterEach
public void afterEach(){
repository.clearStore();
}
@Test
void join() {
//given
Member member = new Member();
member.setName("hello");
//when
Long saveId = memberService.join(member);
//then
Member findMember = memberService.findOne(saveId).get();
Assertions.assertThat(member.getName()).isEqualTo(findMember.getName());
}
@Test
public void 중복_예외_확인() {
//given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
//when
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class,
() -> memberService.join(member2));//예외가 발생해야 한다.
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// try{
// memberService.join(member2);
// }catch(IllegalStateException e){
// assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// }
//then
}
}
MemoryMemberRepository와 MemberService를 선언해준다.

🖐 이전 테스트와는 살짝 다른점이 beforeEach를 활용하는 건데, 각 테스트 시작하기 전에, 실행할 코드들을 적어주는 것이다.
이것으로 도메인, 리포지토리, 서비스 부분을 소스코드로 구현해보는 과정을 거쳤다. 모르는 함수들이 대거 등장해서 많은 어려움을 겪었고, 프론트앤드처럼 바로바로 시각적으로 뭔가 나타나는게 없다보니까 되긴되었네...?하는 느낌이 강하지만, 계속 공부해가면서 프론트와 합쳤을 때를 생각하며 꾸준히 공부하려고 한다.