- [spring] @DataJpaTest 대신 @SpringBootTest를 사용해야 하는 이유 (feat. 테스트 컨텍스트)2025년 03월 09일 18시 30분 49초에 업로드 된 글입니다.작성자: @kimyu0218
난 @DataJpaTest가 더 좋다고 알고 살아왔는데 @DataJpaTest를 사용하는 이유
`@DataJpaTest`는 JPA 컴포넌트를 위한 테스트 어노테이션으로, 레포지토리와 엔티티처럼 JPA와 관련된 빈만 로드한다. 기본적으로 인메모리 임베디드 데이터베이스를 사용하며, `@Entity` 클래스를 스캔하고 레포지토리를 구성한다.
각 테스트 메서드는 트랜잭션으로 처리되며, 테스트가 끝난 후에는 자동으로 롤백된다. 이를 통해 테스트 데이터가 데이터베이스에 남지 않고, 데이터 정합성을 유지할 수 있다.
그럼에도 불구하고 @DataJpaTest 대신 @SpringBootTest를 사용해야 하는 이유
앞에서 살펴봤듯이 `@DataJpaTest`를 사용하면 JPA 관련 컴포넌트만 로드하기 때문에 전체 어플리케이션을 로드하는 불필요한 오버헤드를 줄일 수 있다.
하지만 `@DataJpaTest` 대신 `@SpringBootTest`를 사용하는 게 테스트 실행 속도를 더 개선할 수도 있다..! 전체 빈을 로드하는 `@SpringBootTest`의 성능이 어떻게 더 뛰어날 수 있을까?
이는 스프링이 테스트를 실행할 때마다 컨텍스트를 생성하는 대신, 컨텍스트를 캐싱하여 여러 테스트가 동일한 컨텍스트를 공유하기 때문이다.
컨텍스트 캐싱
스프링 테스트 컨텍스트는 동일한 컨텍스트 구성을 사용하는 테스트에 대해 컨텍스트를 공유한다. 컨텍스트에 로드되는 파라미터를 조합하여 캐시 키를 생성하고, 이를 이용하여 캐시된 컨텍스트를 식별한다. 동일한 구성을 사용하는 컨텍스트는 같은 키 아래 저장되어 컨텍스트를 매번 새롭게 생성하는 오버헤드를 줄일 수 있다.
아래는 컨텍스트 캐시 키를 만드는 데 사용되는 구성 파라미터들의 일부다.`locations` `@ContextConfiguration(locations = [LOCATIONS])` `ApplcationContext`를 로드할 때 사용할 자원 위치 지정 `classes` `@ContextConfiguration(classes = [CLASSES])` `ApplicationContext`를 로드할 때 사용할 구성 클래스 지정 `contextInitializerClasses` `@ContextConfiguration(initializers = [INITIALIZERS])` `ApplicationContext`를 생성하기 전에 실행할 컨텍스트 초기화 로직 지정 `activeProfiles` `@ActiveProfiles` - `propertySourceDescriptors` `@TestPropertySource(locations = [LOCATIONS])` - `propertySourceProperties` `@TestPropertySource(properties = [PROPERTIES])` - `@SpringBootTest` 어노테이션을 사용하면 전체 어플리케이션 컨텍스트를 로드하므로 다양한 의존성을 포함한 통합 테스트를 수행할 수 있다. 즉, 특정 계층에 국한되지 않고 거의 모든 테스트에 적용할 수 있어 컨텍스트를 여러 테스트에서 재사용할 수 있다.
반면에 `@DataJpaTest`는 JPA 관련 컴포넌트만 로드하여 테스트 환경을 가볍게 유지할 수 있지만, JPA 테스트를 위한 별도의 컨텍스트를 생성해야 하므로 컨텍스트를 생성하는 비용이 추가적으로 발생한다.
나는 테스트 컨텍스트 공유를 위해 다음 클래스를 작성했다. 테스트 클래스마다 어노테이션을 직접 작성하는 대신, 공통된 설정을 상위 클래스에서 관리하여 이를 상속받은 모든 테스트 클래스가 동일한 컨텍스트를 공유할 수 있도록 보장했다!@SpringBootTest @ContextConfiguration( initializers = {RedisInitializer.class} ) public class IntegrationTest { @MockBean public ObjectStorageClient objectStorageClient; }
// MissionVerificationTest와 MissionBoardServiceTest는 같은 컨텍스트를 공유한다! class MissionVerificationServiceTest extends IntegrationTest { ... } class MissionBoardServiceTest extends IntegrationTest { ... }
참고자료
- https://docs.spring.io/spring-boot/reference/testing/spring-boot-applications.html#testing.spring-boot-applications.autoconfigured-spring-data-jpa
- https://docs.spring.io/spring-framework/reference/testing/integration.html#testing-ctx-management
- https://docs.spring.io/spring-framework/reference/testing/testcontext-framework/ctx-management/caching.html
'backend > 테스트' 카테고리의 다른 글
[jest] jest 시작하기 (matcher/setup/teardown/mock) (0) 2024.02.03 [node] jest와 supertest로 단위/유닛 테스트 하기 (0) 2024.02.03 다음글이 없습니다.이전글이 없습니다.댓글