스프링 입문 - 회원 리포지토리 테스트 케이스 작성
개발한 기능을 실행해서 테스트 할 때 자바의 main 메서드를 통해서 실행하거나,
웹 어플리케이션의 컨트롤러를 통해서 해당 기능을 실행 해볼 수 잇는데, 이러한 방법은 준비하고 실행하는데 오래 걸리고, 반복 실행하기 어렵고 여러 테스트를 한번에 실행하기 어렵다는 단점이 있다.
자바는 JUnuit이라는 테스트 프레임워크로 테스트를 실행할 수 있다.
test폴더의 java 의 hello의 hellospring 폴더에 repository 라는 이름의 패키지를 만들었다.(보통 테스트 패키지 이름은 기존 패키지와 동일하게 지정한다)
그리고 클래스를 생성해주는데, 테스트할 클래스이름 뒤에 test를 붙여서 이름을 지정해주는 것이 관례다.
얘는 다른데서 쓸 것이 아니기 때문에, 굳이 public으로 만들지 않아도 된다.
save() 메서드를 테스트해 볼 것인데, 앞에 @Test를 작성해해주면,
otg.junit.jupiter.api를 import해준다.
그러면, save()메서드를 실행할 수 있다.
save() 메서드를 실행해보면, save() 메서드가 실행된다.
뭔가 초록불이 나오는데, 실행이 잘 되는 것을 확인 할 수 있다.
그러면 이제 저장이 잘 되는지 테스트를 해보기 위해 코드를 작성해보자.
findeById의 반환타입이 Optional이다.
Optional에서 값을 꺼낼 때는 get()을 이용한다. (사실 get()으로 바로 꺼내는 것이 좋은 방법은 아니지만, 테스트코드같은 곳에서는 이렇게 꺼내도 된다.)
그래서 이렇게 Member객체를 생성하고, 객체에 setName()으로 이름을 지정하고,
repository에 save()로 member를 저장하고,
result로 값을 꺼내도록 했다.
이제 검증을 해봐야 하는데, 어떻게 검증할까?
new로 생성한 member 객체와 db에서 꺼낸 것이 똑같으면, true라고 할 수 있다.
단순하게 이렇게 할 수도 있다.
result == member 인지 출력해보자.
result랑 member가 같은지 테스트했을 때,
result = true가 나왔다.
그런데, 테스트 결과를 이렇게 계속 글자로 볼 수는 없다.
그래서 어떤 기능이 있냐면,
Assert라는 기능이 있다.(단정 메소드(assert method). · JUnit에서 가장 많이 이용되는 단정(assert) 메소드입니다. 단정 메서드로 테스트 케이스의 수행 결과를 판별합니다)
Assertions에 여러가지가 있는데,
org.junit.jupiter.api에서 제공하는 Assertions가 있는데,
이렇게 사용해서 result와 member가 같은지를 확인해볼 수 있다.
command+p 로 옵션을 볼 수 있는데,
이렇게 앞에는 expected, 두번째로는 actual 을 적어줘야 한다.
즉, 우리가 result가 member와 같은지 테스트 하는 것이기 때문에,
기대값은 member이고, 실제 값은 result가 되는 것이다.
이것을 돌려보면,
따로 출력되는 것은 없지만, TestResults옆에 녹색체크가 되었다.
만약에 기댓값과 실제값이 다르면 어떻게 될까?
실제값을 임의로 null로 지정해보자.
그리고 실행해보자.
빨간불이 뜨면서 오류가 낫다. 즉, Test결과가 member와 실제값(null)이 같지 않다고 알려줬다.
그리고 요즈음에는
org.assertj.core.api 에서 제공하는 Assertions도 많이사용하는데,
Assertions를 좀더 편하게 사용할 수 있게 해준다.
그리고 Asserations에 커서를 두고 option+enter를 해서 static 을 선택하면
import문이 추가되면서 이렇게 바뀐다.
이후부터는 assrtThat을 바로 칠 수 있다. 좀더 편할 것이다.
테스트를 돌려보면,
member와 result가 같아서 테스트가 통과되고,
만약 임의로 result를 null값으로 대체해서 돌려보면,
이렇게 x가 뜨면서 테스트에 실패하는 것을 볼 수 있다.
이번에는 findByName()을 테스트 해보자.
2명의 회원을 가입시켯고,
그중 이름이 spring1인 데이터를 대상으로 테스트를 진행했다.
테스트가 성공했다.
밑에 뜨는 빨간색 메시지는, 빌드할 때 JUnit으로 테스트가 진행 되어야 하는데 Gradle로 되어서 발생하는 것이다.
Intellij 설정에서
Settings -> Build, Execution, Deployment -> Build Tools -> Gradle 에서
Build and run using과 Run tests using의 속성을 Intellij IDEA 로 변경해주면 해결할 수 있다.
다시 테스트해보면 사진처럼 잘 성공한 것을 확인할 수 있다.
만약에 "spring2" 라는 이름으로 저장되있는 것을 result에 저장하고,
member1과 비교하면,
result가 meber2가 되므로 member1과 다르므로 Test에 실패한다.
테스트케이스가 의 장점은 여러가지 테스트케이스를 같이 돌릴 수 있다.
클래스 레벨에서 돌리면,
이렇게 테스트가 2개가 돌아간 것을 볼 수 있다.
이번에는 findAll()을 테스트 해보자.
위와같이 테스트코드를 작성했다.
findAll()이므로 객체를 두개정도 생성해 주었다.
그리고 repository.findAll() 을 하면 나오는 결과를 result에 저장했다.
assertThat(result.size()).isEqualTo(2);
를 이용해서 2개를 저장했는데, 과연 2개가 정상적으로 반환될지 테스트를 해보자.
테스트에 성공했다.
이제 전체 테스트를 돌려보자.
클래스단에서 테스트를 돌렸다.
어? findByName()이 이상하다.
아까는 괜찮았는데 지금은 왜 에러가 날까?
테스트 순서를 보면,
fndAll() 이 먼저 테스트 되었다.
그다음에 findByName()이 테스트 되었다.
실행 테스트 순서는 보장이 안된다.
모든 테스트는 순서와 상관없이 다 메서드별로 따로 동작하도록 설계해야한다.
절대로 순서를 의존적으로 설계하면 안된다.
그런데, 지금 보면, fndAll()이 먼저 실행되었다.
findAll()이 먼저 실행되어서 spring1, spring2가 이미 저장되어버렸다.
그래서 그다음에 findByName()을 할 때, 이전에 저장한 spring1, spring2가 나와버린 것이다.
그래서 어떻게 해야 하냐면, 테스트를 하나 끝내고 나면,
데이터를 깔끔하게 클리어 해줘야 한다.
그것을 어떻게 하냐면, 테스트가 끝날때마다 데이터를 저장하는 저장공간(예제에서는 repository)을 깔끔하게 지워주는 코드를 추가해야 한다.
@AfterEach는 클래스의 각 메서드가 끝나고 어떠한 동작을 하는 것이다. 콜백 메서드라고 보면 된다.
즉, save() 끝나고 afterEach()가 호출되고,
findByName()이 끝나고 afterEach()가 호출되고,
findAll()이 끝나고 afterEach()가 호출된다.
이것을 이용해서 어떻게 하면 되냐면,
우선은 MemoryMemberRepository() 만 테스트 하면 되므로
MemberRepository 인터페이스를
이렇게 MemoryMemberRepository로 바꿔주었다.
그리고, MemporyMemberRepository 클래스에
clearStore() 메서드를 추가로 작성해주었다.
clear는 store를 싹 비워준다.
그리고 다시 MemoryMemberRepository로 돌아와서,
afterEach() 메서드 구현부에서 repository.clearStore();를 호출하도록 코드를 작성해준다.
이렇게 하면, Test(테스트 메서드)가 실행되고 끝날 때마다 repository를 한번씩 비워준다.
그러면, 테스트작업은 순서와 상관이 없어진다.
클래스단에서 테스트를 돌려보자.
사진처럼, 테스트가 전부 녹색체크로, 성공했다는 것을 확인할 수 있다.
다시한번 강조하지만,
테스트는 서로간에 순서 의존관계없이 설계되어야 한다.
따라서 하나의 테스트가 끝날때마다, 저장소나 공용 데이터들을 깔끔하게 지워줘야 한다.
이번 예제에서는 먼저 MemoryRepository등 개발을 먼저 한다음에,
테스트 케이스 작성을 했다.
반대로 이것을 완전히 뒤집어서,
테스트 케이스 클래스를 먼저 작성하고,
Member, MemoryRepository를 작성할 수도 있다.
이렇게 테스트 케이스 클래스를 먼저 작성해서
검증할 수 있는 틀을 먼저 만든 상태에서 개발하는 것을 "TDD(테스트 주도 개발)" 라고 한다.
'Spring' 카테고리의 다른 글
스프링 입문 - 회원 서비스 테스트 (0) | 2022.05.18 |
---|---|
스프링 입문 - 회원 서비스 개발 (0) | 2022.05.17 |
스프링 입문 - 회원 도메인과 리포지토리 만들기 (0) | 2022.05.17 |
스프링 입문 - 비즈니스 요구사항 정리 (0) | 2022.05.17 |
스프링 입문 - API (0) | 2022.05.16 |
댓글
이 글 공유하기
다른 글
-
스프링 입문 - 회원 서비스 테스트
스프링 입문 - 회원 서비스 테스트
2022.05.18 -
스프링 입문 - 회원 서비스 개발
스프링 입문 - 회원 서비스 개발
2022.05.17 -
스프링 입문 - 회원 도메인과 리포지토리 만들기
스프링 입문 - 회원 도메인과 리포지토리 만들기
2022.05.17 -
스프링 입문 - 비즈니스 요구사항 정리
스프링 입문 - 비즈니스 요구사항 정리
2022.05.17