본문 바로가기
Spring/SpringBoot

[SpringBoot] MockMVC를 이용하여 API 테스트하기

by J4J 2023. 4. 9.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 mock mvc를 이용하여 api 테스트하는 방법에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

MockMVC란?

 

mock mvc는 스프링을 이용하여 api 테스트를 할 수 있게 도와주는 것 중 하나로 다음과 같은 특징들을 가집니다.

 

  • 서버를 구동시키지 않아도 테스트 가능
  • api 테스트를 하는 것이기 때문에 controller에 구성된 코드들을 테스트
  • client가 api를 요청하는 것처럼 api 경로를 입력하여 테스트하는 방식

 

 

 

스프링 api를 테스트 하는 방법으로 MockMVC를 제외하고도 WebTestClient, TestRestTemplate 등이 있습니다.

 

모두 api를 테스트한다는 공통점을 가지지만 MockMVC는 가상 서버를 동작시키고 WebTestClient와 TestRestTemplate은 실제 서버를 구동시킨다는 차이점을 가지고 있습니다.

 

그렇기 때문에 가상 서버를 활용하는 MockMVC가 더 빠른 속도로 테스트가 이루어진다는 특징이 있는 것으로 알고 있습니다. (아래 테스트 코드들로는 속도 차이가 거의 없었습니다)

 

 

반응형

 

 

Get

 

테스트에 사용될 api는 다음과 같습니다.

 

get api

 

 

 

해당 api를 활용하여 mock mvc를 이용한 테스트 코드를 작성하면 다음과 같습니다.

 

package com.mock.mockmvc;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import java.util.Map;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class Get {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("리턴값 없이 테스트하는 방법")
    void getTest() throws Exception {
        // api 요청
        mockMvc
                .perform(
                        get("/api/mock/getTest") // url
                                .param("name", "myName") // parameter
                                .param("value", "myValue") // parameter
                )
                .andDo(print()) // api 수행내역 로그 출력
                .andExpect(status().isOk()) // response status 200 검증
                .andExpect(jsonPath("method").value("GET")) // response method 데이터 검증
                .andExpect(jsonPath("name").value("myName")) // response name 데이터 검증
                .andExpect(jsonPath("value").value("myValue")); // response value 데이터 검증
    }

    @Test
    @DisplayName("리턴값을 이용하여 테스트하는 방법")
    void getTestReturn() throws Exception {
        // api 요청
        MvcResult mvcResult = mockMvc
                .perform(
                        get("/api/mock/getTest") // url
                                .param("name", "myName") // parameter
                                .param("value", "myValue") // parameter
                )
                .andDo(print())
                .andReturn();

        // response 데이터 변환
        Map<String, String> responseMap =
                new ObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), Map.class);

        // 검증
        Assertions.assertEquals(responseMap.get("method"), "GET"); // response method 데이터 검증
        Assertions.assertEquals(responseMap.get("name"), "myName"); // response name 데이터 검증
        Assertions.assertEquals(responseMap.get("value"), "myValue"); // response value 데이터 검증
    }
}

 

 

 

참고용으로 동일한 결과를 만드는 테스트 코드를 test rest template을 이용하여 작성하면 다음과 같습니다.

 

package com.mock.mockmvc;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;

import java.util.Map;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class GetRestTemplate {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    void getTestTemplate() {
        Map<String, String> responseMap =
                testRestTemplate
                        .getForObject("/api/mock/getTest?name=myName&value=myValue", Map.class);

        Assertions.assertEquals(responseMap.get("method"), "GET");
        Assertions.assertEquals(responseMap.get("name"), "myName");
        Assertions.assertEquals(responseMap.get("value"), "myValue");
    }
}

 

 

 

 

Post

 

테스트에 사용될 api는 다음과 같습니다.

 

post api

 

 

 

해당 api를 활용하여 mock mvc를 이용한 테스트 코드를 작성하면 다음과 같습니다.

 

package com.mock.mockmvc;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class Post {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("리턴값 없이 테스트하는 방법")
    void postTest() throws Exception {
        // body 데이터 적재
        Map<String, String> requestMap = new HashMap<>();
        requestMap.put("name", "myName");
        requestMap.put("value", "myValue");

        String content = new ObjectMapper().writeValueAsString(requestMap);

        // api 요청
        mockMvc
                .perform(
                        post("/api/mock/postTest") // url
                                .contentType(MediaType.APPLICATION_JSON) // contentType 설정
                                .content(content) // body 데이터
                )
                .andDo(print()) // api 수행내역 로그 출력
                .andExpect(status().isOk()) // response status 200 검증
                .andExpect(jsonPath("method").value("POST")) // response method 데이터 검증
                .andExpect(jsonPath("name").value("myName")) // response name 데이터 검증
                .andExpect(jsonPath("value").value("myValue")); // response value 데이터 검증
    }

    @Test
    @DisplayName("리턴값을 이용하여 테스트하는 방법")
    void postTestReturn() throws Exception {
        // body 데이터 적재
        Map<String, String> requestMap = new HashMap<>();
        requestMap.put("name", "myName");
        requestMap.put("value", "myValue");

        String content = new ObjectMapper().writeValueAsString(requestMap);

        // api 요청
        MvcResult mvcResult = mockMvc
                .perform(
                        post("/api/mock/postTest") // url
                                .contentType(MediaType.APPLICATION_JSON) // contentType 설정
                                .content(content) // body 데이터
                )
                .andDo(print())
                .andReturn();

        // response 데이터 변환
        Map<String, String> responseMap =
                new ObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), Map.class);

        // 검증
        Assertions.assertEquals(responseMap.get("method"), "POST"); // response method 데이터 검증
        Assertions.assertEquals(responseMap.get("name"), "myName"); // response name 데이터 검증
        Assertions.assertEquals(responseMap.get("value"), "myValue"); // response value 데이터 검증
    }
}

 

 

 

post도 참고용으로 동일한 결과를 만드는 테스트 코드를 test rest template을 이용하여 작성하면 다음과 같습니다.

 

package com.mock.mockmvc;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PostRestTemplate {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    void postTestTemplate() {
        Map<String, String> requestMap = new HashMap<>();
        requestMap.put("name", "myName");
        requestMap.put("value", "myValue");

        Map<String, String> responseMap =
                testRestTemplate
                        .postForObject("/api/mock/postTest", requestMap, Map.class);

        Assertions.assertEquals(responseMap.get("method"), "POST");
        Assertions.assertEquals(responseMap.get("name"), "myName");
        Assertions.assertEquals(responseMap.get("value"), "myValue");
    }
}

 

 

 

 

 

 

 

 

이상으로 mock mvc를 이용하여 api 테스트하는 방법에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글