본문 바로가기
Backend

[실전! 스프링부트와 JPA활용] 회원 기능 테스트, application.yml

by 햣둘 2025. 4. 4.

테스트 요구사항

1. 회원가입을 성공해야 한다.

2. 회원가입 할 때 같은 이름이 있으면 예외가 발생해야 한다.

 

회원가입 테스트 코드

package jpabook.jpashop.service;

import jakarta.persistence.EntityManager;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
@Transactional // 기본이 롤백
class MemberServiceTest {

    @Autowired
    MemberService memberService;

    @Autowired
    MemberRepository memberRepository;

    @Autowired
    EntityManager em;

    @Test
    //@Rollback(false)
    public void 회원가입() throws Exception {
        //given
        Member member = new Member();
        member.setName("kim");

        //when
        Long savedId = memberService.join(member);

        //then
        //em.flush(); // flush는 영속성 컨텍스트에 있는 변경,등록 내용을 DB에 반영한다는 뜻
        assertEquals(member, memberRepository.findOne(savedId));
    }

    @Test
    public void 중복_회원_예외() throws Exception {
        //given
        Member member1 = new Member();
        member1.setName("kim");

        Member member2 = new Member();
        member2.setName("kim");
        
        //when
        memberService.join(member1);

        //then
        assertThrows(IllegalStateException.class, () -> memberService.join(member2));
    }
}

 

주의! 강의영상과 다른 점

1. JUnit 버전

강의 영상은 JUnit4를 사용하고, 스프링부트 3.x부터는 JUnit5를 사용한다.

따라서 사용하는 패키지가 다르다.

- 영상화면 : org.junit.Test 클래스 사용(JUnit4)

- 수정내역 : org.junit.jupiter.api.Test 클래스 사용(JUnit5)

import static org.junit.jupiter.api.Assertions.*; 사용

 

2. @RunWith 제거

스프링부트 3.x 부터는 @RunWith를 사용하지 않는다.

제거하면 된다.

- 영상화면 : @RunWith(SpringRunner.class) 사용 (JUnit4에서 필요)

- 수정내역 : @RunWith(SpringRunner.class) 사용하지 않음

 

3. 중복회원예외 로직

JUnit5부터 테스트에서 예외를 검증하는 방법이 변경되었다.

JUnit5부터 @Test에 예외를 지정할 수 없다.

- 영상화면 : @Test(expected = IllegalStateException.class) 사용 (JUnit4에서 필요)

- 수정내역 : assertThrows(예외, 람다) 사용. 람다를 사용했을 때 지정한 예외가 발생하지 않으면 테스트가 실패한다.

 

기술 설명

- @RunWith(SpringRunner.class) : 스프링과 테스트 통합 -> 최신 버전에서는 사용하지 않는다. 자동으로 통합된다.

- @SpringBootTest : 스프링부트 띄우고 테스트 (이게 없으면 @Autowired 다 실패)

- @Transactional : 반복 가능한 테스트 지원, 각각의 테스트를 실행할 때마다 트랜잭션을 시작하고 테스트가 끝나면 트랜잭션을 강제로 롤백 (이 어노테이션이 테스트 케이스에서 사용될 때만 롤백)

 

참고) 테스트 케이스 작성 고수 되는 마법 : Given, When, Then

이 방법이 필수는 아니지만 이 방법을 기본으로 해서 다양하게 응용하는 것을 권장한다.

http://martinfowler.com/bliki/GivenWhenThen.html

 

bliki: Given When Then

a bliki entry for Given When Then

martinfowler.com

 

테스트 케이스를 위한 설정

테스트는 케이스 격리된 환경에서 실행하고, 끝나면 데이터를 초기화하는 것이 좋다.

그런 면에서 메모리 DB를 사용하는 것이 가장 이상적이다.

추가로 테스트 케이스를 위한 스프링 환경과, 일반적으로 애플리케이션을 실행하는 환경은 보통 다르므로 설정 파일을 다르게 사용하자.

다음과 같이 간단하게 테스트용 설정 파일을 추가하면 된다.

 

test/resources/application.yml

spring:
#  datasource:
#    url: jdbc:h2:mem:test
#    username: user
#    password:
#    driver-class-name: org.h2.Driver
#
#  jpa:
#    hibernate:
#      ddl-auto: create-drop
#    properties:
#      hibernate:
#        #show_sql: true
#        dialect: org.hibernate.dialect.H2Dialect
#        format_sql: true

logging:
  level:
    org.hibernate.SQL: debug
    org.hibernate.type: trace

 

이제 테스트에서 스프링을 실행하면 이 위치에 있는 설정 파일을 읽는다.

만약 이 위치에 없으면 src/resources/application.yml을 읽는다.

 

스프링부트는 datasource 설정이 없으면, 기본적으로 메모리 DB를 사용하고, driver-class도 현재 등록된 라이브러리를 보고 찾아준다. 추가로 dll-auto도 create-drop 모드로 동작한다. 따라서 데이터소스나 JPA와 관련된 별도의 추가 설정을 하지 않아도 된다.