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

wony·2024년 12월 2일

Java

목록 보기
29/30
  • MockMvc에 대해 이해하자

1) MockMvc

  • 스프링 프레임워크에서 제공하는 웹 애플리케이션 테스트용 라이브러를 의미한다. 이를 사용하면 웹 애플리케이션의 다양한 컴포넌트를 테스트할 수 있다.
  • MockMvc를 사용하면 HTTP 요청을 작성하고 컨트롤러의 응답을 검증할 수 있습니다. 이를 통해 통합 테스트를 실행하지 않고도 컨트롤러의 동작을 확인할 수 있습니다.
  • 쉽게 설명해서 내가 컨트롤러 테스트를 하고싶을 때 실제 서버에 구현한 애플리케이션을 올리지 않고(실제 서블릿 컨테이너를 사용하지 않고) 테스트용으로 시뮬레이션하여 MVC가 되도록 도와주는 클래스이다!

1. MockMvc를 이용한 테스트 목적

  • MockMvc를 이용하여 컨트롤러의 동작을 테스트하는 데 사용됩니다.
  • 컨트롤러의 엔드포인트를 호출하여 HTTP 클라이언트의 요청을 모방하고 적절한 응답을 확인하기 위해 테스트를 수행합니다.
  • 이러한 테스트 과정을 통해 애플리케이션의 서비스 로직이나 API 엔드포인트가 의도한 대로 동작하는지 확인하고, 버그를 발견하고 수정하는 데 도움을 주는 것입니다.

2. MockMvc를 이용한 Controller내의 흐름

  1. TestCase → MockMvc
  • TestCase 내에서 MockMvc 객체를 생성합니다. 이 객체는 테스트할 컨트롤러와 상호작용을 하는 데 사용이 됩니다.
  1. MockMvc → TestDispatcher Servlet
  • MockMvc를 사용하여 원하는 엔드포인트에 요청을 보냅니다. 또한 해당 요청에 필요한 파라미터, 헤더 또는 쿠키 등을 설정합니다.
  • 예를 들어, GET 요청을 보내고 싶다면 perform(MockMvcRequestBuilders.get("/endpoint"))와 같이 요청을 설정합니다.
  • 파라미터 설정은 param("paramName", "paramValue")와 같이 파라미터를 설정할 수 있습니다.
  1. TestDispatcher Servlet → Controller
  • 요청을 실행하고 응답을 받습니다. andExpect 메서드를 사용하여 응답의 상태코드, 헤더, 본문 등을 검증할 수 있습니다.
  1. MockMvc → TestCase
  • 필요한 검증을 추가합니다.
  • 예를 들어, 응답 본문의 내용을 검증하고 싶다면 andExpect(content(). string("expectedValue"))와 같이 검증을 추가합니다.

2) MockMvc, ResultActions

1. MockMvc 주요 메서드

메서드설명
perform()MockMvc를 사용하여 HTTP 요청을 실행합니다.
andExpect()컨트롤러의 응답을 검증합니다.
andExpect(status().isOk())응답 상태 코드가 200인지 확인합니다.
andExpect(content().string("expected"))응답 본문의 내용이 "expected"인지 확인합니다.
andExpect(jsonPath("$.property").value("expected"))JSON 응답에서 특정 속성의 값이 "expected"인지 확인합니다.
andExpect(view().name("expectedView"))응답에 대한 뷰의 이름이 "expectedView"인지 확인합니다.
andExpect(model().attribute("attributeName", "expectedValue"))모델 속성의 값이 "expectedValue"인지 확인합니다.
andExpect(redirectedUrl("expectedUrl"))리다이렉트된 URL이 "expectedUrl"인지 확인합니다.
  • MockMvc 메서드를 이용한 사용예시
@ExtendWith(MockitoExtension.class)     // Junit5 - Mockito 연동
class CodeControllerTest {

    private MockMvc mockMvc;   // HTTP 호출을 위한 MockMVC 사용

    @BeforeEach
    void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(codeController).build();
    }

    @Test
    public void testExample() throws Exception {
        mockMvc.perform(get("/example"))                                        // "/example"로 GET 요청 수행
                .andExpect(status().isOk())                                     // 상태 코드 200인 성공적인 응답을 기대합니다
                .andExpect(content().string("expected"))                        // 응답 내용이 "expected"와 같을 것으로 기대합니다
                .andExpect(jsonPath("$.property").value("expected"))            // JSON 속성 "property"의 값이 "expected"와 같을 것으로 기대합니다
                .andExpect(view().name("expectedView"))                         // 뷰 이름이 "expectedView"와 같을 것으로 기대합니다
                .andExpect(model().attribute("attributeName", "expectedValue")) // 모델 속성 "attributeName"의 값이 "expectedValue"와 같을 것으로 기대합니다
                .andExpect(redirectedUrl("expectedUrl"));                       // "expectedUrl"로의 리다이렉트를 기대합니다
    }
}

2. ResultActions 주요 메서드

  • MockMvc를 사용하여 실행한 ‘HTTP 요청에 대한 결과’를 나타냅니다. 이를 통해 컨트롤러의 응답을 검증하고 원하는 동작을 수행할 수 있습니다.
메서드설명
andReturn()해결된 MvcResult 객체를 반환합니다.
andReturn(MvcResult)반환할 MvcResult를 설정합니다.
andDo(ResultHandler)결과에 대해 추가 작업을 수행합니다.
andDo(ResultMatcher)결과에 ResultMatcher를 추가합니다.
andExpect(ResultMatcher)결과에 대한 기대치로 ResultMatcher를 추가합니다.

ResultActions 메서드 사용 예시

import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

public class SampleTest {
    private MockMvc mockMvc;

    // ...

    public void sampleTest() throws Exception {
        ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/sample"));
        resultActions
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.message").value("Hello, World!"));
        // Add more assertions or actions as needed
    }
}

3) MockMvc에서 사용되는 어노테이션

어노테이션설명
@ExtendWith(MockitoExtension.class)Mockito를 사용하여 모킹하기 위해 테스트 클래스에 적용됩니다.
@WebMvcTest웹 MVC 테스트를 위해 스프링 컨텍스트를 구성합니다.
@AutoConfigureJsonTestersJSON 테스트를 위해 JsonTester의 자동 구성을 활성화합니다.
@AutoConfigureMockMvcMockMvc를 자동으로 구성하는 데 사용됩니다.
@Mock모킹 대상 객체를 생성하여 주입합니다.
@MockBeanSpring 컨텍스트에서 Mock 객체를 생성하여 주입합니다.
@SpringBootTest스프링 부트 애플리케이션의 통합 테스트를 위해 스프링 컨텍스트를 구성합니다.
@BeforeEach각각의 테스트 메서드가 실행되기 전에 실행되는 메서드를 지정합니다.
@Test테스트 메서드를 지정합니다.

4) MockMvc 사용법

컨트롤러를 테스트한다고 가정하자!

@Test
@BlogMockUser
@DisplayName("글 작성 요청시 title값은 필수다.")
void test2() throws Exception {
    // given
    PostCreate request = PostCreate.builder()
            .content("내용입니다.")
            .build();

    String json = objectMapper.writeValueAsString(request);
    // mockMvc에게 컨트롤러에 대한 정보를 입력하자.

    // expected
    mockMvc.perform(post("/api/posts")     // 해당 url로 요청
                    .contentType(APPLICATION_JSON) // Json 타입으로 지정
                    .content(json))    // json으로 내용 등록
            .andExpect(status().isBadRequest())// 응답 status를 isBadRequest로 테스트
            .andExpect(jsonPath("$.code").value("400"))
            .andExpect(jsonPath("$.message").value("잘못된 요청입니다."))
            .andExpect(jsonPath("$.validation.title").value("타이틀을 입력하세요."))
            .andDo(print()); // 응답값 print
}
  1. MockMvc를 생성한다.
  2. MockMvc에게 요청에 대한 정보를 입력한다.
  3. 요청에 대한 응답값을 Expect를 이용하여 테스트한다.
  4. Expect가 모두 통과하면 테스트 통과
  5. Expect가 1개라도 실패하면 테스트 실패
profile
안녕하세요. wony입니다.

0개의 댓글