Spring Boot 테스트 슬라이스 선택법: @WebMvcTest·@DataJpaTest·@SpringBootTest 차이
메타 설명: Spring Boot 4.1에서 @WebMvcTest, @DataJpaTest, @SpringBootTest가 각각 무엇을 로딩하는지 비교하고, Controller·JPA·통합 테스트에 맞는 선택 기준과 실행 가능한 예제를 정리합니다.
테스트가 느려졌다고 무조건 단위 테스트로 바꿀 필요는 없습니다. 더 흔한 원인은 Controller 하나를 검증하면서 데이터베이스와 웹 서버까지 포함한 전체 애플리케이션 컨텍스트를 매번 띄우는 것입니다.
Spring Boot의 테스트 슬라이스는 검증 대상에 필요한 자동 설정만 선택해서 로딩합니다. 웹 계층은 @WebMvcTest, JPA 계층은 @DataJpaTest, 여러 계층의 연결은 @SpringBootTest로 나누면 테스트의 목적과 실패 원인이 선명해집니다.
세 애노테이션의 역할
| 구분 | 주로 로딩하는 범위 | 실제 서버 | 적합한 검증 |
|---|---|---|---|
@WebMvcTest |
MVC 인프라, Controller, Advice, Filter | 실행하지 않음 | URL 매핑, 검증, JSON, HTTP 상태 |
@DataJpaTest |
Entity, JPA Repository, DataSource | 실행하지 않음 | 쿼리, 매핑, 제약조건 |
@SpringBootTest |
전체 애플리케이션 컨텍스트 | 옵션 | 계층 연결, 설정, 전체 흐름 |
슬라이스 테스트는 “가짜 테스트”가 아닙니다. Spring MVC나 JPA라는 실제 프레임워크 동작은 포함하되, 이번 테스트와 관계없는 계층만 제외합니다.
@WebMvcTest로 HTTP 계약 검증하기
회원 조회 Controller가 서비스 결과를 JSON으로 반환한다고 가정합니다.
@RestController
@RequestMapping("/members")
class MemberController {
private final MemberService memberService;
MemberController(MemberService memberService) {
this.memberService = memberService;
}
@GetMapping("/{id}")
MemberResponse find(@PathVariable Long id) {
return memberService.find(id);
}
}
record MemberResponse(Long id, String email) {}
Spring Boot 4.1의 @WebMvcTest는 MockMvcTester를 자동 구성합니다. 서비스는 @MockitoBean으로 대체해 Controller의 계약만 확인합니다.
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
@WebMvcTest(MemberController.class)
class MemberControllerTest {
@Autowired
MockMvcTester mvc;
@MockitoBean
MemberService memberService;
@Test
void 회원을_조회하면_JSON을_반환한다() {
given(memberService.find(1L))
.willReturn(new MemberResponse(1L, "steve@example.com"));
assertThat(mvc.get().uri("/members/1"))
.hasStatusOk()
.bodyJson()
.extractingPath("$.email")
.isEqualTo("steve@example.com");
}
}
@WebMvcTest는 일반 @Service나 @ConfigurationProperties Bean을 자동으로 스캔하지 않습니다. 필요한 설정 객체는 @EnableConfigurationProperties, 추가 구성은 @Import로 명시합니다. Spring Security가 있으면 필터 체인도 적용되므로 인증을 통째로 끄기보다 보안 테스트 지원으로 필요한 사용자를 구성하는 편이 좋습니다.
@DataJpaTest로 쿼리와 매핑 검증하기
Repository 테스트의 핵심은 Mockito 호출 횟수가 아니라 실제 JPQL, 매핑, DB 제약조건입니다.
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
@DataJpaTest
class MemberRepositoryTest {
@Autowired
MemberRepository memberRepository;
@Test
void 이메일로_회원을_찾는다() {
memberRepository.saveAndFlush(new Member("steve@example.com"));
assertThat(memberRepository.findByEmail("steve@example.com"))
.isPresent();
}
}
@DataJpaTest는 Entity와 Spring Data JPA Repository를 구성하고 기본적으로 테스트 종료 시 트랜잭션을 롤백합니다. 내장 DB가 클래스패스에 있으면 자동으로 사용할 수 있지만, 운영 DB가 MariaDB라면 Testcontainers를 연결해 SQL 문법·collation·락 차이까지 확인해야 합니다. 저장 시점의 제약조건 예외를 검증할 때는 SQL을 미루지 않도록 saveAndFlush() 또는 flush()를 사용합니다.
@SpringBootTest가 필요한 순간
다음 질문은 전체 컨텍스트가 필요합니다.
- Controller, Service, Repository가 실제 Bean으로 연결되는가?
- 운영 설정과 조건부 Bean이 함께 적용되는가?
- 보안 필터부터 DB까지 요청 한 건이 통과하는가?
- 실제 포트에서 HTTP 클라이언트와 직렬화가 동작하는가?
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MemberApiIntegrationTest {
// 실제 HTTP 호출과 테스트 DB를 함께 검증
}
전체 통합 테스트는 중요한 경로에만 둡니다. 모든 예외 분기와 입력 조합을 여기서 반복하면 실행 시간이 길고, 실패했을 때 어느 계층이 원인인지 찾기 어렵습니다.
흔한 실수
- 하나의 테스트 클래스에
@WebMvcTest와@DataJpaTest를 함께 붙입니다. 여러 슬라이스의 동시 사용은 지원되지 않습니다. @WebMvcTest에서 Service가 없다는 오류가 나자@SpringBootTest로 바꿉니다. 필요한 협력자는@MockitoBean이나@Import로 의도를 드러냅니다.- Repository를 H2로만 검증하고 MariaDB에서도 같다고 단정합니다. DB 종속 기능은 실제 엔진으로 확인합니다.
- 모든 테스트를
@SpringBootTest로 작성합니다. 전체 연결을 검증할 때만 비용을 지불합니다. - 테스트가 통과했다는 이유로 목적을 생략합니다. 클래스 이름과 테스트 메서드가 검증 계층과 결과를 설명해야 합니다.
검증 순서
개발 중에는 Service의 순수 로직 테스트와 슬라이스 테스트를 먼저 실행합니다. CI에서는 전체 테스트를 실행하되, 느린 통합 테스트의 시간과 실패율을 따로 관찰합니다. 마지막으로 Testcontainers가 실제 MariaDB 이미지를 사용했는지 select version() 같은 쿼리로 확인할 수 있습니다.
핵심 요약
- HTTP 계약은
@WebMvcTest, JPA 매핑과 쿼리는@DataJpaTest로 좁힙니다. - 계층 연결과 운영 설정은
@SpringBootTest로 검증합니다. - Spring Boot 4.1의 테스트 애노테이션과 패키지는 3.x 예제와 다를 수 있으므로 현재 공식 문서를 기준으로 import합니다.
- 슬라이스 테스트와 실제 MariaDB Testcontainers 테스트를 조합하면 속도와 운영 일치성을 함께 확보할 수 있습니다.
함께 읽기:
- Spring Boot 4.1 + Testcontainers로 MariaDB 통합 테스트하기
- Spring Boot @ConfigurationProperties 검증
- Spring Boot REST API 에러 응답 설계
- Spring Boot 지원 기간과 버전 선택
최종 확인: 2026-08-02
공식 출처:
'Programming > Spring Boot' 카테고리의 다른 글
| Spring Boot Actuator readiness·liveness 설정: 배포 트래픽을 안전하게 제어하는 방법 (0) | 2026.08.06 |
|---|---|
| Spring Boot Actuator readiness·liveness 설정: 배포 트래픽을 안전하게 제어하는 방법 (0) | 2026.08.04 |
| Spring Boot @ConfigurationProperties 검증: 잘못된 운영 설정을 시작 단계에서 차단하기 (0) | 2026.07.31 |
| Spring Boot Graceful Shutdown 설정: 배포 중 요청을 안전하게 종료하는 방법 (0) | 2026.07.28 |
| Spring Boot LTS는 없을까? 4.1·4.0·3.5 지원 기간과 버전 선택 (0) | 2026.07.14 |