JAVA/JAVA | Spring 학습기록

[Spring] Spring boot Test 코드 작성해보기 (TDD 연습)

kth990303 2021. 5. 5. 11:13
반응형

스프링 강의를 들으면서, 그리고 주변 개발자들이 포스팅한 것을 보면서

tdd의 중요성을 조금씩 느끼곤 있었지만,

에러가 뜰까봐 두려움 때문에, 그리고 직접 스프링 실행해서 db를 직접 cmd창으로 확인해보면 된다는 합리화때문에 test폴더에서 test 코드를 작성한 적이 없었다.

 

kth990303.tistory.com/46

 

[Spring] MySQL+JPA+Spring+Gradle 환경설정 및 실습

그동안 백준 풀면서 스프링 공부를 소홀히 한 게 느껴져서 오랜만에 스프링 공부도 할 겸, 간단한 회원조회 실습을 해보기로 했다. 말그대로 기초적인 간단한 실습을 복습 겸 하는거라, Domain에 M

kth990303.tistory.com

그러나, 오늘 위 포스팅의 다음버전을 마저 하기 위해

crud 기능이 제대로 돌아가는지 테스트하기 위해 테스트코드를 작성해보았고

아래 사진과 같이 테스트 코드를 작성하는데에 첫 발걸음을 내딛는데 성공하였다!

스프링부트 웹 프로젝트에서 처음으로 스스로 테스트코드 작성해보았다

위 테스트코드는 

 

  1. 회원 조회가 제대로 되는지
  2. 회원 가입이 제대로 되는지
  3. 회원 검색이 제대로 되는지

이 세가지를 파악하기 위해 작성한 코드이다.


코드 첨부 및 기능 설명

나는 IndexController 클래스의 테스트 코드를 작성하고 싶었고,

그 방법은 아래와 같다.

위 사진처럼 클래스명에 마우스를 놓고 alt + Enter 를 누르면 위와 같이 Create Test 가 생긴다. 

클릭해주면 된다.

JUnit5가 21.05.05기준 최신 junit이다.

그럼 위와 같이 화면이 뜰텐데 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를 작성하고 싶으면 그냥 무조건 붙여준다고 보면 될 듯 하다.

 

자세한 내용은 아래 블로그를 참고하자.

goddaehee.tistory.com/211

 

[스프링부트 (9)] SpringBoot Test(2) - @SpringBootTest로 통합테스트 하기

[스프링부트 (9)] SpringBoot Test(2) - @SpringBootTest로 통합테스트 하기 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ 스프링 부트 통합 테스트 하기 (@SpringBootTest)] 입니다. : ) 0. 들어가기 앞서 이..

goddaehee.tistory.com

참고로 JUnit4 에서는 @RunWith(SpringRunner.class) 어노테이션을 붙여줘야 했으나,

JUnit5에서는 붙일 필요가 없다.

아래 글을 참고하자.

www.inflearn.com/questions/145880

 

질문. - 인프런 | 질문 & 답변

선생님 진짜 입 꾹다물고 야생형으로 가보려고했는데 이게 궁금해서 못참겠습니다.. @RunWith(SpringRunner.class) @SpringBootTest 앞쪽 스프링할때 테스트케이스 작성시에 클래스위에 아무것도 없었는데 

www.inflearn.com

 

@Autowired

의존관계 자동 주입을 의미한다. 

스프링에서 매우매우 중요한 기능 중 하나인데,

사실 이 어노테이션을 잘 모르면 스프링 기능에 대해 좀 더 공부해볼 것을 추천한다. (나도 더 공부해야되는데ㅋㅋㅋ...)

테스트 코드가 회원이 db에 잘 저장되는지, 그리고 repository에서 db에 있는 회원을 잘 검색하는지 파악하기 위함이므로 memberRepository의 메소드를 사용하기 위해 memberRepository를 의존관계로 주입한 것이다.

 

@Test

스프링 부트 test에서만 붙이는 게 아닌, 단순 자바 코드라도 Test코드일 경우 @Test를 붙여주면 편하다.

이 메소드가 test method임을 명시해줌으로써 ide에서 테스트를 진행할 때, 문제되는 test method는 무엇인지, 혹은 몇개인지 알려줄 수 있을 뿐 아니라, 각종 테스트 기능을 제공해줄 수 있게 된다.

 

@Transactional

트랜잭션을 자동으로 수행해주며, 예외나 에러가 발생하면 test 중 db에 입력된 값들을 rollback (reset이라 보면 된다)해준다. 아직 나도 jpa 공부단계여서 자세한 내용은 아래 블로그를 참고해야 할 듯 하다.

jeong-pro.tistory.com/228

 

Transaction 동작 원리, JDBC 기본에 충실한 과정(JPA, Hibernate, Spring's @Transactional)

JDBC 트랜잭션에 대한 이해 Transaction 기본 동작 원리를 익히기 위해서 점진적인 접근을 할 것입니다. (두괄식X 미괄식O) 궁극적으로는 @Transactional 이 어떻게 돌아가는지를 알아볼 것이지만, 우선은

jeong-pro.tistory.com

mommoo.tistory.com/92

 

[Spring] @Transactional 사용시 주의해야할 점

Spring @Transactional 주의점 안녕하세요. 오늘은 Spring 의 @Transactional 어노테이션을 사용할 때, 주의점에 대해 포스팅합니다. Spring 에서 JPA 기술을 쓸 때 빼놓을 수 없는 기능중 하나는 @Transa.

mommoo.tistory.com

@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 문법을 통해 회원을 쉽게 찾을 수 있음을 알게 됐고,

검색 기능까지 추가해보았다.

kihoonkim.github.io/2017/01/27/JPA(Java%20ORM)/2.%20JPA-%EC%98%81%EC%86%8D%EC%84%B1%20%EA%B4%80%EB%A6%AC/

 

(JPA - 2) 영속성(Persistence) 관리

JPA를 사용하면 어플리케이션과 데이터베이스 사이에 영속성 컨텍스트(Persistence Context)라는 개념을 두고 데이터를 관리한다.영속성 컨텍스트란 무엇인지 어떻게 생성, 관리되는지 알아보자. 참

kihoonkim.github.io

 

그리고 이왕 만든 기능, 테스트코드도 작성해보자 싶어서

여러 포스팅들을 참고한 끝에 테스트코드 작성 또한 성공하였다.

 

다음 포스팅에서 아마 MySQL+JPA+Spring+Gradle 회원조회 코드(Controller, Service, Repository, Domain)를 설명하는 시간을 가질 듯 하다. 

 

JPA 공부 어서 열심히 해야겠다.

 

+네트워크 공부를 하다가, 대용량 트래픽 처리를 위해 stateless 설계가 중요하다는 말을 들었는데, 솔직히 아직은 정확히 무슨 소린지 잘 모르겠지만, 서버 개발에 관심이 생겨 이것저것 찾아보았다.

서버 터질려고 할 때마다 개발자들은 어떻게 그에 대한 대비를 하는것일까? 너무 궁금한데 아직은 내가 미숙하여 대용량 트래픽 관련해서 아는 것이 없다. (redis? kafka? 이게 뭐람)

실습에 익숙해지고 java 웹개발이 어느 정도 진행된다면 대용량 트래픽 또한 공부해보고 싶다.

 

반응형