슬라이스 테스트

애플리케이션의 특정 계층(슬라이스)만 선택적으로 로딩하여 검증하는 Spring Boot 특화 테스트 기법입니다.

왜 필요한가?

@SpringBootTest는 모든 Bean을 로딩하므로 느리고 무겁습니다. 슬라이스 테스트는 테스트에 필요한 계층의 Bean만 로딩하여 통합 테스트의 신뢰성과 단위 테스트의 속도 사이 균형을 잡습니다.

@SpringBootTest     → [Controller + Service + Repository + DB + ...] 전부 로딩
@WebMvcTest         → [Controller + MVC 관련]만 로딩
@DataJpaTest        → [Repository + JPA 관련]만 로딩

주요 슬라이스 어노테이션

어노테이션대상 계층로딩되는 Bean대표 용도
@WebMvcTestController@Controller, @ControllerAdvice, Filter 등요청/응답, 검증, 예외 처리
@DataJpaTestRepository@Repository, EntityManager, 내장 DB쿼리, 매핑, 연관관계 검증
@DataMongoTestMongoDBMongo Repository, TemplateMongoDB 쿼리 검증
@RestClientTest외부 APIRestTemplate, WebClient외부 API 호출/응답 검증
@JsonTestJSON 직렬화ObjectMapper, @JsonComponentJSON 변환 로직 검증
@WebFluxTestWebFlux Controller@Controller (리액티브)리액티브 엔드포인트 검증

Java 예시

1. @WebMvcTest — Controller 계층 테스트

@WebMvcTest(OrderController.class)
class OrderControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean  // Service 계층은 Mock으로 대체
    private OrderService orderService;

    @Test
    @DisplayName("주문 조회 시 200 OK와 주문 정보를 반환한다")
    void getOrder() throws Exception {
        // Given
        OrderResponse response = new OrderResponse(1L, "키보드", 10_000);
        given(orderService.findById(1L)).willReturn(response);

        // When & Then
        mockMvc.perform(get("/api/orders/{id}", 1L))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.productName").value("키보드"))
                .andExpect(jsonPath("$.price").value(10_000));
    }

    @Test
    @DisplayName("존재하지 않는 주문 조회 시 404를 반환한다")
    void getOrder_notFound() throws Exception {
        given(orderService.findById(99L))
                .willThrow(new OrderNotFoundException(99L));

        mockMvc.perform(get("/api/orders/{id}", 99L))
                .andExpect(status().isNotFound());
    }
}

2. @DataJpaTest — Repository 계층 테스트

@DataJpaTest
class ProductRepositoryTest {

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private TestEntityManager em;

    @Test
    @DisplayName("가격 범위로 상품을 조회한다")
    void findByPriceRange() {
        // Given
        em.persist(new Product("마우스", 5_000, 50));
        em.persist(new Product("키보드", 10_000, 30));
        em.persist(new Product("모니터", 300_000, 10));
        em.flush();

        // When
        List<Product> result = productRepository
                .findByPriceBetween(1_000, 50_000);

        // Then
        assertThat(result).hasSize(2)
                .extracting("name")
                .containsExactlyInAnyOrder("마우스", "키보드");
    }
}

테스트 방식 비교

항목단위 테스트슬라이스 테스트@SpringBootTest
Bean 로딩없음 (순수 Java)해당 계층만전체
속도매우 빠름빠름느림
외부 의존성Mock내장 DB 또는 Mock실제 또는 테스트 환경
검증 범위메서드/클래스특정 계층전체 흐름
Spring 컨텍스트미사용부분 로딩전체 로딩

슬라이스 테스트 시 주의사항

실무 팁: Controller는 @WebMvcTest, Repository는 @DataJpaTest로 각 계층을 빠르게 검증하고, 계층 간 연동이 중요한 핵심 시나리오만 @SpringBootTest로 테스트하는 전략이 효과적입니다.

CSLOG에서 보기