임대일

Spring Boot Junit5 이해하기: @WebMvcTest, @SpringBootTest 본문

스프링

Spring Boot Junit5 이해하기: @WebMvcTest, @SpringBootTest

limdae94 2024. 4. 13. 13:31

Spring Boot Junit5 이해하기: @WebMvcTest, @SpringBootTest

스프링 부트에서 Junit 라이브러리로 테스트 코드를 작성할 때 @WebMvcTest, @SpringBootTest 어노테이션 두 가지를 가장 많이 사용합니다. 이번 장에서는 @WebMvcTest, @SpringBootTest 두 어노테이션의 차이점에 대해 학습합니다.

1. Mock, MockMvc

  • Mock

    실제 객체를 만들기엔 비용과 시간이 많이 들거나 의존성이 길게 걸쳐져 있어 제대로 구현하기 어려울 경우, 가짜 객체를 만들어 사용하는데 이것을 Mock 이라 한다. 따라서 Mock 은 테스트할 때 필요한 실제 객체와 동일한 모의 객체를 만들어 테스트의 효용성을 높이기 위해 사용한다.

  • MockMvc

    MVC에 관련된 Mock 객체를 말한다. MockMvc는 웹 어플리케이션을 애플리케이션 서버에 배포하지 않고 테스트 MVC 환경을 만들어 요청 및 전송, 응답 기능을 제공해주는 유틸리티 클래스이다. 웹 애플리케이션의 컨트롤러 및 RESTful 엔드포인트를 테스트할 때 실제 HTTP 요청을 보내지 않고도 테스트할 수 있다. 대신에 가짜 HTTP 요청을 만들고 해당 요청에 대한 응답 검증을 수행한다.

쉽게 정리해서 설명하자면, Mock 은 실제 객체가 아닌 테스트 전용 객체이고 MockMvc 는 MVC에 관련된 Mock 객체로서 컨트롤러와 관련된 테스트를 수행하기 위한 객체이다.

2. Mock 주입 시 차이

@WebMvcTest, @SpringBootTest 각각 적용된 테스트 코드마다 MockMvc 를 @Autowired 로 주입하는 방식에 차이가 있다. 또한 빈으로 등록되는 범위에도 차이가 있습니다. 먼저 Mock 주입 시 차이점에 대해 학습한다.

  • @SpringBootTest

    @SpringBootTest
    class SpringBootTest {
        @Autowired 
        MockMvc mockMvc; // 주입 X
    }

    @SpringBootTest 가 선언된 테스트 코드에 MockMvc 를 @Autowired 로 주입하기 위해 위의 코드처럼 작성하면 주입이 되지 않고 에러가 발생한다. 그 이유는 @SpringBootTest 가 MockMvc 를 빈으로 등록시키지 않기 때문이다. 따라서 MockMvc 를 빈으로 등록하기 위해 @AutoConfigureMockmvc 어노테이션을 추가로 작성해야 한다.

  • @AutoConfigureMockMvc 추가

    @SpringBootTest
    @AutoConfigureMockMvc // @AutoConfigureMockmvc 어노테이션을 추가
    class SpringBootTest {
        @Autowired MockMvc mockMvc; // 주입 O
    }

    따라서 @SpringBootTest 와 함께 @AutoConfigureMockMvc 를 작성해야 MockMvc 객체를 사용할 수 있다.

  • @WebMvcTest

    @WebMvcTest
    class SpringBootTest {
        @Autowired MockMvc mockMvc; // 주입 O
    }

    @WebMvcTest 는 MockMvc 를 빈으로 등록한다. 따라서 위의 코드처럼 @MvcMvcTest 작성된 테스트 코드는 MockMvc 를 @Autowired 로 객체가 주입된다.

3. 빈 등록 범위 차이

  • @SpringBootTest

    @SpringBootTest
    @AutoConfigureMockMvc
    class SpringBootTest {
        @Autowired 
        MockMvc mockMvc; // mockMvc 주입 O
    
        @Autowired 
        UserController userController; // Controller 주입 O
    
        @Autowired 
        UserRepository userRepository; // Repository 주입 O
    
        @Autowired 
        UserService userService; // Service 주입 O
    }

    @SpringBootTest 는 프로젝트의 컨트롤러, 리포지토리, 서비스 모두 @Autowired 으로 주입이 가능하다.

  • @WebMvcTest

    @WebMvcTest
    class SpringBootTest {
        @Autowired 
        MockMvc mockMvc; // MockMvc 주입 O
    
        @Autowired 
        UserController userController; // Controller 주입 O
    
        @Autowired 
        UserRepository userRepository; // Repository 주입 X
    
        @Autowired 
        UserService userService; // Service 주입 X
    }

    @WebMvcTest 는 Web Layer 와 관련된 빈을 등록한다. 따라서 컨트롤러만 정상적으로 주입하고, @Component 로 등록된 리포지토리와 서비스는 주입되지 않는다. @WebMvcTest 가 작성된 테스트 코드에서 리포지토리와 서비스를 주입하기 위해 @MockBean 을 사용하여 Mock 객체에 빈으로 등록해야 한다.

  • Web Layer 에 속한 항목

    Security, Filter, Interceptor, request/response Handling, Controller
  • @MockBean 추가

    @WebMvcTest
    class SpringBootTest {
        @Autowired 
        MockMvc mockMvc; // MockMvc 주입 O
    
        @Autowired 
        UserController userController; // Controller 주입 O
    
        @MockBean 
        UserRepository userRepository; // Repository 주입 O -> @MockBean 
    
        @MockBean 
        UserService userService; // Service 주입 O -> @MockBean 
    }

4. @SpringBootTest, @WebMvcTest 차이 정리

  • @SpringBootTest 사용

    1. MockMvc 객체를 빈으로 등록하지 않기 때문에 @AutoConfigureMockMvc로 빈으로 등록해야 한다.
    2. 프로젝트에 있는 스프링 빈을 모두 등록해서 테스트에 필요한 의존성을 추가해준다.
  • @SpringBootTest 장점

    1. 프로젝트에 있는 모든 스프링 빈을 등록하므로, 테스트에 필요한 객체를 주입받아서 쉽게 사용 가능하다.
    2. 실제 환경과 가장 유사하게 테스트가 가능하다.
  • @SpringBootTest 단점

    1. 모든 스프링 빈을 등록할 때 프로젝트의 전체 컨텍스트를 로드해서 빈을 주입하기 때문에 속도가 느리다.
    2. 테스트 단위가 크기 때문에 디버깅이 어려울 수 있다.

💡 단위 테스트와 같은 기능 테스트가 아닌, 전체적인 프로그램 작동이 제대로 이루어 지는지 검증하는 통합 테스트 시에 많이 사용한다!

  • @WebMvcTest 사용

    1. MockMvc 객체를 빈으로 등록해서 @Autowired로 MockMvc 주입이 가능하다.
    2. Web Layer 관련 빈들만 등록하기 때문에, @Component로 등록된 빈은 @MockBean으로 주입해야 한다.
  • @WebMvcTest 장점

    1. Web Layer 관련 빈만 로드하기 때문에, 속도가 @SpringBootTest보다 빠르다.
    2. 통합테스트에서 테스트가 어려운 작은 단위 테스트들을 @WebMvcTest로 진행할 수 있다.
  • @WebMvcTest 단점

    1. Mock 객체를 사용하기 때문에 실제 환경에서는 다른 오류가 발생할 수 있다.

💡 이러한 이유로, 컨트롤러 테스트, 단위 테스트 시에 많이 사용한다!