스프링 강의를 들으면서, 그리고 주변 개발자들이 포스팅한 것을 보면서
tdd의 중요성을 조금씩 느끼곤 있었지만,
에러가 뜰까봐 두려움 때문에, 그리고 직접 스프링 실행해서 db를 직접 cmd창으로 확인해보면 된다는 합리화때문에 test폴더에서 test 코드를 작성한 적이 없었다.
그러나, 오늘 위 포스팅의 다음버전을 마저 하기 위해
crud 기능이 제대로 돌아가는지 테스트하기 위해 테스트코드를 작성해보았고
아래 사진과 같이 테스트 코드를 작성하는데에 첫 발걸음을 내딛는데 성공하였다!
위 테스트코드는
- 회원 조회가 제대로 되는지
- 회원 가입이 제대로 되는지
- 회원 검색이 제대로 되는지
이 세가지를 파악하기 위해 작성한 코드이다.
코드 첨부 및 기능 설명
나는 IndexController 클래스의 테스트 코드를 작성하고 싶었고,
그 방법은 아래와 같다.
위 사진처럼 클래스명에 마우스를 놓고 alt + Enter 를 누르면 위와 같이 Create Test 가 생긴다.
클릭해주면 된다.
그럼 위와 같이 화면이 뜰텐데 OK 눌러주면된다.
그러면 테스트코드 클래스가 생성이 될건데,
나는 테스트를 위해 아래와 같이 코드를 작성하였다.
package shop210504.pracshop.controller;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;
import shop210504.pracshop.domain.Member;
import shop210504.pracshop.repository.MemberRepository;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
public class IndexControllerTest {
@Autowired
MemberRepository memberRepository;
@Test
@Transactional
@Rollback(false)
public void joinMember(){
Member member=new Member();
member.setName("choisk0531");
member.setTier("Gold");
Member joinMember = memberRepository.save(member);
Member findMember = memberRepository.findMember(joinMember.getId());
assertThat(findMember.getId()).isEqualTo(member.getId());
assertThat(findMember).isEqualTo(joinMember);
}
}
@SpringBootTest
스프링부트 어플리케이션 테스트를 실행할 때 필요한 대부분의 의존성을 제공해준다. @SpringBootApplication을 실행하면서 스프링 빈 등록 및 의존성 관련 어노테이션 기능들을 제공해주므로 Spring boot Application으로 Test를 작성하고 싶으면 그냥 무조건 붙여준다고 보면 될 듯 하다.
자세한 내용은 아래 블로그를 참고하자.
참고로 JUnit4 에서는 @RunWith(SpringRunner.class) 어노테이션을 붙여줘야 했으나,
JUnit5에서는 붙일 필요가 없다.
아래 글을 참고하자.
www.inflearn.com/questions/145880
@Autowired
의존관계 자동 주입을 의미한다.
스프링에서 매우매우 중요한 기능 중 하나인데,
사실 이 어노테이션을 잘 모르면 스프링 기능에 대해 좀 더 공부해볼 것을 추천한다. (나도 더 공부해야되는데ㅋㅋㅋ...)
테스트 코드가 회원이 db에 잘 저장되는지, 그리고 repository에서 db에 있는 회원을 잘 검색하는지 파악하기 위함이므로 memberRepository의 메소드를 사용하기 위해 memberRepository를 의존관계로 주입한 것이다.
@Test
스프링 부트 test에서만 붙이는 게 아닌, 단순 자바 코드라도 Test코드일 경우 @Test를 붙여주면 편하다.
이 메소드가 test method임을 명시해줌으로써 ide에서 테스트를 진행할 때, 문제되는 test method는 무엇인지, 혹은 몇개인지 알려줄 수 있을 뿐 아니라, 각종 테스트 기능을 제공해줄 수 있게 된다.
@Transactional
트랜잭션을 자동으로 수행해주며, 예외나 에러가 발생하면 test 중 db에 입력된 값들을 rollback (reset이라 보면 된다)해준다. 아직 나도 jpa 공부단계여서 자세한 내용은 아래 블로그를 참고해야 할 듯 하다.
@Rollback(false)
테스트 중에 db에 입력된 값을 테스트 전 원래상태로 rollback해주는 어노테이션이다. Default값으로 true이며, 나는 db에 직접 값이 들어가는지 확인하기 위해 false로 지정해주었다.
test code에서 확인 뿐만 아니라, db에서도 확인하고 싶었기 때문이다.
자, 그럼 @Test가 붙여진 test method를 간단하게 살펴볼까?
public void joinMember(){
Member member=new Member();
member.setName("choisk0531");
member.setTier("Gold");
Member joinMember = memberRepository.save(member);
Member findMember = memberRepository.findMember(joinMember.getId());
assertThat(findMember.getId()).isEqualTo(member.getId());
assertThat(findMember).isEqualTo(joinMember);
}
먼저 {name: choisk0531, tier: Gold} 인 member를 생성해주었다.
repository.save(member)를 통해 회원가입을 시켰고,
repository.findMember(joinMember.getId())를 통해 회원가입시킨 멤버를 select하였다.
assertThat이란, test code에서 JUnit이 테스트 기능을 제공하기 위한 AssertJ 문법 중 하나이다.
findMember의 id와 member의 id가 다르면 의도한 바와 다르므로, AssertThat에서 에러를 띄워준다.
밑에 코드도 마찬가지다.
AssertJ 문법 공부의 필요성이 느껴지는가? (공부할 게 하나 더 늘었다..)
이제 테스트 코드를 실행하면 아래와 같이 된다.
왼쪽에 초록색 체크 표시가 보이는가?
테스트들이 잘 성공했다는 의미이다.
테스트 로그들을 자세히 보면
Hibernate: insert into member (name, tier) values (?, ?)
도 볼 수 있을 것이다.
위의 테이블에는 kth990303만이 있는 것을,
아래 테이블에는 choisk0531 멤버 또한 가입돼있는 것을 확인할 수 있다.
@Rollback(false)로 어노테이션을 붙여줬으므로 rollback이 진행되지 않은 것 또한 의도대로 잘 됐음을 알 수 있다.
원래 실습에서 회원 조회만 하려 했는데,
em.find jpa 문법을 통해 회원을 쉽게 찾을 수 있음을 알게 됐고,
검색 기능까지 추가해보았다.
그리고 이왕 만든 기능, 테스트코드도 작성해보자 싶어서
여러 포스팅들을 참고한 끝에 테스트코드 작성 또한 성공하였다.
다음 포스팅에서 아마 MySQL+JPA+Spring+Gradle 회원조회 코드(Controller, Service, Repository, Domain)를 설명하는 시간을 가질 듯 하다.
JPA 공부 어서 열심히 해야겠다.
+네트워크 공부를 하다가, 대용량 트래픽 처리를 위해 stateless 설계가 중요하다는 말을 들었는데, 솔직히 아직은 정확히 무슨 소린지 잘 모르겠지만, 서버 개발에 관심이 생겨 이것저것 찾아보았다.
서버 터질려고 할 때마다 개발자들은 어떻게 그에 대한 대비를 하는것일까? 너무 궁금한데 아직은 내가 미숙하여 대용량 트래픽 관련해서 아는 것이 없다. (redis? kafka? 이게 뭐람)
실습에 익숙해지고 java 웹개발이 어느 정도 진행된다면 대용량 트래픽 또한 공부해보고 싶다.
'JAVA > JAVA | Spring 학습기록' 카테고리의 다른 글
[Spring] 스프링이 태어난 이유_서블릿, JSP로 만든 MVC의 한계 (0) | 2021.07.06 |
---|---|
[Spring] lombok의 @Builder와 JpaRepository를 도입해보았다 (0) | 2021.05.17 |
[Spring] CRUD 기능 실습 중 @DeleteMapping 관련 에러 (0) | 2021.05.11 |
[Spring] MySQL+JPA+Spring+Gradle 회원조회 Read 실습 (0) | 2021.05.10 |
[Spring] MySQL+JPA+Spring+Gradle 환경설정 및 실습 (0) | 2021.05.04 |