이번 글에서는 Repository 계층의 단위 테스트를 어떻게 작성하는지에 대해 학습한 내용을 정리하고자 합니다.
현재 상황
Spring Boot : 3.0.6
Java : JDK17
MySQL 8.0.33
QueryDSL 사용
JUnit : JUnit5
테스트 DB : in-memory DB(H2)
테스트 환경 설정
application-test.yml 작성
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
globally_quoted_identifiers: true
format_sql: true
show-sql: true
generate-ddl: true
database: h2
properties:
hibernate.dialect: org.hibernate.dialect.MySQL8Dialect
h2:
console:
enabled: true
설정 설명
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL
mem:test
: 인메모리 DB로 생성됨 (테스트 종료 시 삭제)DB_CLOSE_DELAY=-1
: 연결이 끊겨도 DB 유지DATABASE_TO_UPPER=false
: 컬럼명 등에서 대문자 자동 변환 방지MODE=MySQL
: H2 데이터베이스가 MySQL 문법을 따르도록 설정
hibernate.dialect
: Hibernate가 SQL을 생성할 때 MySQL Dialect를 사용하도록 설정ddl-auto: create-drop
: 테스트 시작 시 테이블을 생성하고 종료 시 제거globally_quoted_identifiers
: 모든 식별자(테이블, 컬럼 등)를 백틱(`)으로 감싸도록 설정하여 예약어 충돌 방지 및 대소문자 구분 명확히 함
TestConfig 작성
QueryDSL 기반 Repository 테스트 시 JPAQueryFactory
가 필요합니다. 테스트 환경에서는 Spring Boot가 이를 자동으로 등록해주지 않기 때문에, 수동으로 Bean 등록이 필요합니다.
👉 작성할 Repository가 QueryDSL를 사용하지 않아도, 현재 프로젝트에서 QueryDSL를 사용 중이므로 설정을 추가해주어야 합니다.
@TestConfiguration
@EnableJpaAuditing
public class TestConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
테스트 코드 작성
테스트 클래스 어노테이션
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(TestConfig.class)
@DataJpaTest
: JPA 관련 Bean만 로딩하여 테스트 속도와 안정성을 확보합니다.@AutoConfigureTestDatabase
: 테스트에서 임베디드 DB(H2)를 자동 교체하지 않도록 설정합니다.@Import(TestConfig.class)
: 필요한 설정들을 별도로 주입합니다.
Cart 조회 성공 테스트
@Test
@DisplayName("Customer로 Cart 조회 성공")
void find_cart_by_customer_success() {
// given
Customer customer = CustomerFixture.createCustomer();
customerRepository.save(customer);
Cart cart = Cart.createCart(customer);
cartRepository.save(cart);
// when
Optional<Cart> result = cartRepository.findByCustomer(customer);
// then
assertThat(result).isPresent();
assertThat(result.get().getCustomer()).isEqualTo(customer);
}
CustomerFixture.createCustomer()
를 통해 테스트 고객을 생성합니다.실제 DB에 저장된 고객을 기반으로 Cart를 생성한 후, 저장합니다.
findByCustomer
로 조회했을 때 Cart가 반환되는지 확인합니다.연관된 Customer 정보까지 정확히 일치하는지도 검증합니다.
Cart 조회 실패 테스트
@Test
@DisplayName("Customer로 Cart 조회 실패 - 존재하지 않음")
void find_cart_by_customer_fail_not_found() {
// given
Customer customer = CustomerFixture.createCustomer();
// when
Optional<Cart> result = cartRepository.findByCustomer(customer);
// then
assertThat(result).isEmpty();
}
저장되지 않은 Customer로 Cart를 조회했을 때 결과가 비어 있는지 확인합니다.
전체 테스트 코드
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import store.myproject.onlineshop.domain.cart.Cart;
import store.myproject.onlineshop.domain.customer.Customer;
import store.myproject.onlineshop.fixture.CustomerFixture;
import store.myproject.onlineshop.global.config.TestConfig;
import store.myproject.onlineshop.repository.customer.CustomerRepository;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import(TestConfig.class)
class CartRepositoryTest {
@Autowired
CartRepository cartRepository;
@Autowired
CustomerRepository customerRepository;
@Test
@DisplayName("Customer로 Cart 조회 성공")
void find_cart_by_customer_success() {
// given
Customer customer = CustomerFixture.createCustomer();
customerRepository.save(customer);
Cart cart = Cart.createCart(customer);
cartRepository.save(cart);
// when
Optional<Cart> result = cartRepository.findByCustomer(customer);
// then
assertThat(result).isPresent();
assertThat(result.get().getCustomer()).isEqualTo(customer);
}
@Test
@DisplayName("Customer로 Cart 조회 실패 - 존재하지 않음")
void find_cart_by_customer_fail_not_found() {
// given
Customer customer = CustomerFixture.createCustomer();
// when
Optional<Cart> result = cartRepository.findByCustomer(customer);
// then
assertThat(result).isEmpty();
}
}
Reference
- https://0soo.tistory.com/40
- https://0soo.tistory.com/41
- https://jyami.tistory.com/124