본문 바로가기
개발 지식/Spring Framework

[Test] Controller Test mockMvc 활용

by 에르주 2022. 4. 26.
반응형

실무 개발을 진행하면서 배포 Branch에 Merge Request를 하기 위해서는 필수적으로 Test 파일을 작성해야 했다. 

많은 테스트 방법들을 배우고 있지만 그 중 API Controller 테스트 방법 중 하나인 mockMvc를 활용하게 되었고 이를 정리하려고 한다.

(개발자 단위 테스트, 통합 테스트 구별할 것..)

 

mockMvc 이란 무엇일까?

 Controller 테스트를 위해 서버에 애플리케이션을 배포하지 않아도 MVC 패턴 및 동작을 테스트 할 수 있는 클래스이다.

말 그대로 mockMvc MVC 패턴의 mock 형태라고 이해하면 될 것 같다.

 

코드로 직접 확인해보자

 

일단 Test 진행할 컨트롤러는 다음과 같다.

@Slf4j
@RestController
public class APIController {


  @GetMapping("/api/v1/food")
  public Map<String, Object> retrieveFoodsOnAPI(@RequestParam(name = "criteria", required = false) String criteria) {

    Map<String, Object> FoodsMap = new HashMap<>();
    if ("회".equals(criteria)) {

      List<Food> foodList = Arrays.asList(new Food("회", "광어", 200),
                                          new Food("회", "우럭", 300),
                                          new Food("회", "대방어", 500));

      FoodsMap.put("body", foodList);
    }
    return FoodsMap;
  }
}

Controller 실행 예시

 

이제 mockMvcTest 클래스를 작성을 통해 Controller Test를 작성해보자.

 

@Autowired로 MockMvc를 주입하려고 하면 bean을 찾을 수 없다라고 하는데 @AutoConfigureMockMvc 어노테이션을 클래스에 선언해준다.

 

 

 

@AutoConfigureMockMvc
@SpringBootTest
public class mockMvcTest {

  private static final Cookie cookie = new Cookie("token", "test1234");

  @Autowired
  public MockMvc mockMvc;

  @Test
  @DisplayName("Get 회가 좋아요 - /api/v1/food")
  public void FishFoodMockTest() throws Exception {

	// 1) Parameter
    MultiValueMap<String, String> param = new LinkedMultiValueMap<>(); 
    param.add("criteria", "회");											

	// 2) mockMvc 실행
    ResultActions resultActions = mockMvc.perform(get("/api/v1/food")
        .params(param)
        .cookie(cookie)
        .contentType(MediaType.APPLICATION_JSON));

	// 3) 결과
    resultActions.andExpect(status().isOk())
                 .andExpect(jsonPath("$.body[0].name").value("광어"))
                 .andExpect(jsonPath("$.body[1].name").value("우럭"))
                 .andExpect(jsonPath("$.body[2].name").value("대방어"))
                 .andDo(print());

  }

 

 

 

1) Parameter 

 

Parameter 값은 MultiValueMap으로 설정할 수 있다. MultiValueMap의 구현체인 LinkedMultiValueMap으로 Paramter 값을 설정하였다.

MultiValueMap<String, String> param = new LinkedMultiValueMap<>(); 
param.add("criteria", "회");

 

물론. param 메서드를 통해 하나하나 매핑할 수도 있다. 

param

 

2) mockMvc 실행

 
이제 위에 설정한 Paramter 값을 활용해서 개발한 API 테스트를 수행하는  mockMvc를 구현해보자.
 
ResultActions resultActions = mockMvc.perform(get("/api/v1/food")
    .params(param)
    .cookie(cookie)
    .contentType(MediaType.APPLICATION_JSON));
 
 
  • get("/api/v1/food") : GET 방식의 EndPoint가 /api/v1/food 인 API를 호출한다.
  • params : 위에서 설정했던 paramter 값
  • cookie : API 조회에 필요한 Cookie 또한 넣을 수 있다.
  • contentType : xml, json 등 API 호출 결과 값 유형을 설정할 수 있다.

 

3) 결과

mockMvc가 수행한 결과값을 가지고 우리가 의도한대로 API 데이터가 반환하는지 확인한다.

resultActions.andExpect(status().isOk())
             .andExpect(jsonPath("$.body[0].name").value("광어"))
             .andExpect(jsonPath("$.body[1].name").value("우럭"))
             .andExpect(jsonPath("$.body[2].name").value("대방어"))
             .andDo(print());

 

  • andExpect 메서드는 내가 예상하는 결과값 입력하여 mockMvc의 결과값과 비교한다.
    • status().isOk() : 정상동작
    • jsonPath(...) 결과 값에 대한 json 파싱 결과 비교
  • andDo 메서드는 mockMvc를 수행하고 나서의 동작을 설정한다.
    • print() mockMvc의 실행 Log을 확인 할 수 있다.

 

print()로 실행하는 mockMvc의 결과 이며

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /api/v1/food
       Parameters = {criteria=[회]}
          Headers = [Content-Type:"application/json;charset=UTF-8", Cookie:"token=test1234"]
             Body = null
    Session Attrs = {}

Handler:
             Type = com.mspark.springstudy.controller.APIController
           Method = com.mspark.springstudy.controller.APIController#retrieveFoodsOnAPI(String)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json"]
     Content type = application/json
             Body = {"body":[{"kindValue":"회","name":"광어","kcal":200},{"kindValue":"회","name":"우럭","kcal":300},{"kindValue":"회","name":"대방어","kcal":500}]}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
테스트 결과

 

테스트 또한 에러 없이 잘 수행한 것을 확인 할 수 있다.

 

끝.

 

 

 

 

 

 

반응형

댓글