-

[스프링 부트 Step 10] - 회원 서비스 테스트 본문

백엔드 기술 정리/스프링 부트

[스프링 부트 Step 10] - 회원 서비스 테스트

흣차 2022. 1. 1. 01:08
728x90
반응형

이번에는 저번에 만들었던 회원 서비스 기능을 테스트를 할 것입니다.

테스트할 때에도 아주 유용한 단축키가 있습니다.

클래스에 마우스를 대고 Ctrl + Shift + T를 누르면 Create new Test가 뜹니다.

name도 그대로 MemberServiceTest라고 자동 입력되어있으니 정말 편하네요.

밑의 join, findMembers, findOne을 모두 체크해주고 OK누릅니다.

그럼 이렇게 메서드가 생성됩니다.

자 하나씩 채워넣어 봅시다.

제일 먼저 회원가입이 잘 되는지 보겠습니다.

보통은 영어권에서 취업하지 않는한 국내 기업들은 메서드명을 쓸 때 한글 이름도 많이 씁니다.

언제까지고 영어도 못하는데 findmembers, findmember, savemember이렇게 메서드를 만들면 외국인들이야 편하겠지만 우리는 상당히 헷갈릴 때가 있습니다.

그래서 회원가입(), 회원등록(), 회원조회() 이렇게 등록하셔도 괜찮습니다.

이렇게 입력해도 무방

 

일단 이렇게 MemberService의 객체를 생성합니다.

그리고 회원가입() 메서드를 만들건데, 추천하는 기본 양식이 있습니다.

given, when, then 문법이에요.

테스트는 생각해보면 given이라는 상황이 주어지고 when을 실행했을 때 then이 나오는 양식을 주로 따릅니다.

이렇게 나누면 굉장히 편리한데, given문법을 보고 아 저 상황에 저게 주어지구나. when을 보고 아 저때 실행하는구나. then을 보고 아 저런 결과가 나와야 하는구나를 주석만보고도 예측이 가능하고 도움이 됩니다.

테스트를 처음할 때는 이 패턴으로 하는걸 굉장히 추천합니다.

자 그럼 내부에는 어떻에 입력하면 좋을까요.

자 이렇게 입력하면 Member의 member가 주어지고 이 member의 setName은 hello가 됩니다.

자 그런데  memberService에 member를 join시키고 saveId를 반환해서 가져올 때 그 결과 갖고온 saveId에서의 Member를 findMember에 담고 기존 member의 getName과 findMember의 getName이 같은지 비교를 해봅니다.

이런 결과가 나왔다면 성공입니다.

근데 꼭 알고 넘어가야할 부분이 있습니다.

사실 테스트는 정상적인 flow에서 테스트하는 것도 중요한데, 경계값에서 flow를 분석하는것도 중요합니다.

정보처리기사 공부하면서, 학부생때도 들었는데 이런걸 보통 경계값 분석이라고도 하죠.

특정한 범위가 주어져있는 다항함수에 대해서 x의 어디 범위부터 어디범위까지가 연속이고 연속이지 않고 하는거 우리가 배웠었잖아요? 그 특정한 x의 값에 따라 연속이고, 연속이 아닌게 나뉘었듯이 테스트케이스에서도 어떤 값에 대해서만 예외가 발생할 수도 있습니다.

그래서 테스트에서는 반드시 무조건 성립하는 테스트의 경우와 예외의 경우도 꼭 살펴보아야 합니다.

따라서 지금까지 한 테스트는 사실 반쪽짜리 테스트이기도 합니다.

한 번 살펴봅시다.

이 join의 핵심은 저장이 되는 것도 중요한데, 중복 회원 검증 로직을 잘 파서 중복회원이 나올 때 메세지가 뜨는지도 살펴보아야 합니다.

이렇게 입력해줍시다.

그리고 member1과 member2의 setName둘 다 똑같이 sprint로 입력하면 member1과 member2가 같아집니다.

그 상태에서 try catch문을 쓸거에요. 

일반적으로 member1과 member2를 넣고 에러메세지를 확인하려면 예외적인 상황을 연출해야 해요.

그래서 try문에는 memberService에 member2를 join시키고 fail함수를 실행합니다.

fail()

Fail the test without a failure message.
Although failing with an explicit failure message is recommended, this method may be useful when maintaining legacy code.

즉, 실패했을 경우 메세지를 출력하지 않고 테스트를 실패하겠단 뜻입니다.

이때 실패되었을 떄 튕겨져 나오는 메세지 중 IllegatStateException을 e에 담아, 이 e가 위에 상기된 이미 등록된 회원입니다.와 일치하는지 여부를 판단합니다.

결과도 깔끔합니다.

일부러 예외도 한 번 줘봤습니다. 어때요?

expected부분이 기대값이고 but was가 나와야 하는 값입니다. 근데 두개가 다르니까 에러가 뜨지요? 

이런식으로 테스트를 하여 실제 예측값이 어떨지를 예측할수도 있습니다.

근데 이거때문에 try catch문을 넣는게 좀 애매할 수 있습니다.

그래서 JUnit에서는 따로 문법을 제공합니다.

바로 assertThrows라는 것인데요.

이렇게 입력하시면 asserThrows에 IllegalStateException 클래스를 발생해야하고 람다를 터트립니다.

이 로직을 태울 때 memberService에 member2를 join시키면 예외가 터져야합니다.

그러면 그 결과 짠

성공적으로 이 예외가 터져서 초록불이 들어왔습니다!

만약 저기서 IllegalStateException이 아니라면 다른 예외를 입력하면 테스트가 실패하게됩니다.

오직 IllegalStateException만 이 예외를 통과할 수 있습니다.

그럼 이 메세지를 반환하려면, 당연히 반환 메서드가 있어야 합니다.

그래서 Ctrl + alt + V를 누르면 

이렇게 되고 이 메세지를 e로 받아옵시다.

그럼 받아온 메세지를 이렇게도 확인할 수 있습니다.

근데 다른 테스트에서 sprint를 여러 개 받아와버리면 지난 MemoryMemberRepository에서처럼 했듯이 레포지토리에 여러 개가 중복으로 들어가서 오류가 날 수 있습니다.

그래서 이를 예방하기 위해 

똑같이 memberRepository를 clear할 필요가 있습니다.

이처럼 모든 테스트의 memberRepository를 싹 비울 수 있습니다.

근데 잘 생각을 해보시면 MemoryMemberRepository의 memberRepository와 MemberService의 memberRepository가 원래는 같은 클래스에서 생성했지만 결과적으로 두 군데에서 각각 생성하면서 다른 데이터 입력값을 input하는걸로 보아 다른 객체로 보는 것이 맞겠습니다.

따라서 저장소를 다른 repository를 쓴 것입니다.

그러므로 같은 인스턴스를 쓰게 만드려면 이렇게 설정합니다.

MemberService클래스로 들어가서 이렇게 변경합니다.

이렇게 설정하는 이유는 이 파라미터를 외부에서 넣어주게끔 해야하기 때문입니다.

memberRepository를 직접 new로 생성하는게 아니라 외부에서 memberRepository를 받아와서 넣어준다면 MemoryMemberRepository()를 테스트에서 따로 생성하지 않아도 됩니다.

그래서 테스트로 넘어와서

이렇게 하면 BeforeEach어노테이션을 통해, 실행 전에 늘memberRepository와 memberService를 선언해서 실행하게 됩니다.

이렇게 되면 같은 MemoryMemberRepository를 사용하게 됩니다.

MemberService입장에서 보면 내가 직접 new하지 않고 외부에서 memberRepository를 외부에서 넣어주는 꼴이 됩니다.

이를 뭐라하냐면 Dependency Injection 즉, DI라고 합니다. 의존성 주입이 바로 여기서 등장합니다.

 

감사합니다.

728x90
반응형
Comments