💻 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
실제 강의 링크
작성할 테스트 코드의 서비스 함수이다.
아래 서비스 함수는 회원 가입 및 회원 찾기 기능이다.
회원의 서비스의 기능은 비지니스 로직의 이름으로
회원 DB에 관련된 기능은 좀 더 개발스럽게 작명하는게 좋다.
아래 코드를 기반해서 테스트 코드를 작성해보자
public Long join(Member member){
//중복 이름 회원 허용 X
/**
* 중복 회원을 허용 하지 않는 로직을 구현하느 것이 핵심이다.
* 먼저 회원이 있나 찾아야함
*
* 영한님은 옵셔널 반환을 굳이 안한다
*/
// Option 반환 인자 선언 후 실행 이 아닌 바로 isPresnet 적용
// Optional<Member> result = memberRepository.findByName(member.getName());
// result.ifPresent(m->{
// throw new IllegalStateException("이미 존재하는 회원입니다.");
// });
validateDuplicate(member); // 중복 회원 검증
memberRepository.save(member);
return member.getId();
}
private void validateDuplicate(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);
}
영한님이 테스트 코드를 작성할 떄 기본 구조로 제안한 것은
given / when /then 구조이다.
이 구조를 기반으로 테스트 케이스를 작성한다.
각 회원들을 가입이 정상 동작 하는지 또 중복 회원을 잘 걸러내는지 확인한다
여기서 테스트 케이스의 목적은 정상 동작 확인도 있지만
예외 상황을 잘 처리 하는지도 중요
test 회원이 가입했을떄 test라는 회원이 다시 가입을 하면 예외처리가 되어 이미 존재하는 회원이라는 에러 메시지를 반환한다.
class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
//MemoryMemberRepository memberRepository = new MemoryMemberRepository();//이거를 두개를 쓸 이유가 없음 새로운 인스턴스로 할당하는게 좋지 않다.
@BeforeEach
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService(memberRepository);
}
@AfterEach
public void afterEach(){
memberRepository.clearStore();
}
@Test
void 회원가입() {
//given
Member member = new Member();
member.setName("test");
//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("test");
Member member2 = new Member();
member2.setName("test");
//when
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// try {
// memberService.join(member2);
// fail();
// }catch (IllegalStateException e){
// Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// }
//then
}
@Test
void findMembers() {
}
@Test
void findOne() {
}
}
현재 생성된 회원 리포지토리는 static으로 Map이 구성
만약 static이 아닌 경우에는 new로 새로운 리포지토리를 회원 정보에 새로 할당한다면 빌드 환경과 테스트 환경에서 서로 다른 리포지토리를 사용하는 것으로 추후 치명적인 문제로 이어질 수 있다.
그렇기 때문에 MemberService 객체에서 선언과 동시에 할당하는 것이 아닌 생성자를 이용해서 할당하는 방법으로 문제를 해결한다.
유닛 테스트, 통합 테스트와 같은 테스트는 웹 개발에서 중요한 요소이고 앞으로 우테코에서 지향하는 TDD에 대해서 더 깊게 알아보겠다.