[Spring/TestCode] WebMvcTest or SpringBootTest(+AutoConfigureMockMvc)

2025. 3. 10. 23:54Dev/TestCode

 

 

📝 어떤 프로젝트를 맡게 되어 개발을 하게 될 때 테스트 코드를 잘 작성하게 된다면, 운영 환경에서 겪게 될 문제점들 중 많은 부분들을 사전에 방지할 수 있습니다. Spring Boot 프레임워크를 이용한 개발 환경에서, 문득 @SpringBootTest와 @WebMvcTest의 차이점이 궁금하여 글을 작성하게 되었습니다.


 

MoctMvc

Spring Boot 프레임워크와 Junit을 이용하여 테스트 코드를 작성할 때, MoctMvc를 이용할 수 있습니다. 여기서 MockMvc는 스프링에서 제공해주는 테스트용 라이브러리입니다!

 

Spring 문서에서는 MoctMvc의 목표를 다음과 같이 소개하고 있는데요

 

MockMvc aims to provide more complete testing support for Spring MVC controllers without a running server. 

...

MockMvc is a server-side test framework

that lets you verify most of the functionality of a Spring MVC application using lightweight and targeted tests.

 

서버를 running 하지 않고도 Spring MVC controllers를 지원하기 위한 testing 방법이라고 소개하고 있습니다.

 

MockMvc 객체를 주입받아 테스트를 진행할 수 있는데요!! 아래와 같은 메서드를 이용하게 됩니다.

andExpect() 실행된 결과를 확인하고 싶을 때
andDo() 일반적인 action을 수행했을 때
andReturn() 결과를 다루기 위해 실행 결과를 return 받을 때

@WebMvcTest

 

컨트롤러 계층을 test 할 수 있는 애노테이션으로, 컨트롤러만을 이용하기에 테스트 속도가 빠르다는 장점이 있습니다.

@WebMvcTest(ExceptionTest.TestController.class)
@Import(ExceptionTest.TestConfig.class)
public class ExceptionTest {

//이하 생략

 

다만, Contoller 을 테스트하기에.. Service나 Repository를 test하기 위해서는 @MockBean을 이용해야 합니다.

 

 

@SpringBootTest + @AutoConfigureMockMvc

위에서 언급한 @WebMvcTest처럼 Test할 때 사용되는 애노테이션입니다. 하지만 웹 애플리케이션 전체를 대상을 test하기에, 전체 bean을 불러오게 됩니다. @Service, @Repository 를 사용하는 객체들도 이용하게 되는데요! 따라서 @WebMvcTest보다 상대적으로 테스트 속도가 느리다는 단점이 있습니다.

@SpringBootTest
@AutoConfigureMockMvc
@Import(ExceptionTest.TestConfig.class)
public class ExceptionTest {

//이하 생략

 

@WebMvcTest @SpringBootTest + @AutoConfigureMockMvC
웹 애플리케이션 전체 (예: Controller, Service, Repository) Controller 단
느린 속도 빠른 속도
MockBean X MockBean O

 


참고 예제 (static class를 이용하여 test 코드를 작성해봤습니다~!

 

일반 코드(200 return)와 에러 발생(exception) 코드를 호출하는 controller test입니다.

@Import(ExceptionTest.TestConfig.class)
public class ExceptionTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testHelloEndpoint() throws Exception {
        mockMvc.perform(get("/test"))
                .andExpect(status().isOk())
                .andExpect(content().string("ok"));
    }

    @Test
    void testCustomExceptionHandling() throws Exception {
        mockMvc.perform(get("/error"))
                .andExpect(status().isBadRequest())
                .andExpect(content().string("exception occurred"));
    }

    @TestConfiguration
    static class TestConfig {

        @Bean
        public TestController testController() {
            return new TestController();
        }

        @Bean
        public TestExceptionHandler testExceptionHandler() {
            return new TestExceptionHandler();
        }
    }


    @RestController
    static class TestController {

        @GetMapping("/test")
        public ResponseEntity<String> hello() {
            return ResponseEntity.ok("ok");
        }

        @GetMapping("/error")
        public ResponseEntity<String> error() {
            throw new CustomException("exception occurred");
        }
    }

    @RestControllerAdvice
    static class TestExceptionHandler {

        @ExceptionHandler(CustomException.class)
        public ResponseEntity<String> handleCustomException(CustomException e) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    }

    static class CustomException extends RuntimeException {
        public CustomException(String message) {
            super(message);
        }
    }

}

 

References

1. [Java] Spring Boot MockMvc 이해하기 : 테스트 흐름 및 사용예제

2. @WebMvcTest에 대한 올바른 사용법 및 시행착오

3. [Spring Test] @WebMvcTest VS @AutoConfigureMockMvc

4. [Official] Spring MockMvc

5. [Official] Testing the Web Layer

'Dev > TestCode' 카테고리의 다른 글

[TestCode/Spring] TestCode에 Lombok 사용하기  (0) 2024.03.10
[TestCode/Spring] RANDOM_PORT  (1) 2024.03.09
[TestCode/IntelliJ] show passed / test coverage  (0) 2024.03.09
[TestCode] JUnit Test  (0) 2023.09.13