이번 포스트에서는 Spring @MVC의 Controller를 테스트하는 방법에 대해서 알아보자.
MockMvc 설정
MockMvc?
Controller를 만들고 잘 동작하는지 확인하기 위해서 매번 스프링 애플리케이션을 실행하고 브라우저를 통해서 동작을 확인하는데는 매우 손이 많이 간다. 이 상황에서 파라미터의 전달, attribute, 화면 이동 등을 검증하는 일은 쉬운 일이 아니다. 또한 웹이 제대로 동작하는지 확인하기 위해서는브라우저나 WAS처럼 우리가 프로그래밍하지 않은 요소가 개입된다.
따라서Controller의 단위 테스트를 위해서는MockMvc이라는 객체가 사용된다. MockMvc는 앞서 살펴봤던 @Mock 처럼 가짜로 테스트를 위해브라우저나 WAS의 동작을 똑같이 처리해줄 수 있는 환경이라고 생각하면 된다. MockMvc를 이용해브라우저에서 발생하는 요청을 가상으로 만들고 컨트롤러가 응답하는 내용을 기반으로 검증을 수행한다.
legacy spring에서 MockMvc 설정
legacy spring에서 MockMvc를 얻기 위해서는 3개의 annotation이 필요하다.
@TypeExcludeFilters(WebMvcTypeExcludeFilter.class): @Controller,@ControllerAdvice,@JsonComponent,Converter, Filter,HandlerInterceptor등웹과관련된빈을스캔해서등록 한다. (@Service 등은 @MockBean 으로 처리)
@AutoConfigurerCache: 기본 CacheType으로CacheType.NONE을 설정해서 데이터를캐싱하지 않는다.
@AutoConfigureWebMvc: SpringMVC테스트에 필요한 환경을 로딩한다.
@AutoConfigureMockMvc: MockMvc를 자동으로 구성한다.
특정 @Controller만을 테스트 대상으로 지정할 때는 controllers ( = value) 속성을 이용한다.
MockMvc를 자동으로 구성하기 때문에 legacy에 비해 테스트 코드가 훨씬 간단해 졌다.
요청(request)을 만들어서 실행(perform)하면 돌아오는 응답(response)에 대해 기대값을 검증(expect)한다.
MockMvc 객체는 크게 3가지 동작을 갖는다.
메서드
설명
MockMvc.perform(요청)
MockHttpServletRequestBuilder를 통해서 생성된 요청을 가상 서버에 전달한다.
ResultActions.andExpect(검증 내용)
요청 결과 즉 응답에 대해 검증을 수행한다. 검증의 항목은 ResultMatchers를 반환하는 handler(), status(), model(), view() 등 메서드들을 활용한다.
ResultActions.andDo(처리할 내용)
콘솔 출력등 검증 외 추가로 처리할 일을 ResultHandler 타입으로 작성한다.
요청 만들기 및 perform
요청은 MockMvcRequestBuilders의 static 메서드인 get, post, put, delete, fileUpload 등을 이용해서 MockHttpServletRequestBuilder 객체를 생성하는 것에서 시작한다. MockHttpServletRequestBuilder는 ServletRequest를 구성하기에 필요한 다양한 메서드를 제공한다.
메서드명
설명
param / params
요청 파라미터를 설정한다.
header / headers
요청 헤더를 설정한다.
cookie
쿠키를 설정한다.
requestAttr
request scope에attribute를 설정한다.
flashAttr
flash scope에attribute를 설정한다.
sessionAttr
session scope에 attribute를 설정한다.
locale
Locale 정보를 설정한다.
characterEncoding
요청의 인코딩 정보를 설정한다.
contentType
Enum인 MediaType으로 요청의 컨텐트 타입을 설정한다.
file
fileUpload로 ServletRequestBuilder를 생성한 경우 업로드 파일을 지정한다.
위 메서드들은 method chaining을 지원하기 때문에 쭉 연결해서 작성하는 것이 일반적이다. 만들어진 요청은 MockMvc의 perform 메서드에 파라미터로 설정해준다.
// given : 테스트에 필요한 요소들을 생성한다.Stringurl="/add";
MultiValueMap<String, String> map = newLinkedMultiValueMap<>();
map.add("a", "10");
map.add("b", "20");
CookienameCookie=newCookie("name", "홍길동");
// when : builder 패턴을 이용해서 요청을 생성하고 실행한다.MockHttpServletRequestBuilderbuilder= get(url).params(map).cookie(nameCookie);
ResultActionsresult= mockMvc.perform(builder);
andExpect
perform의 결과로 ResultActions가 반환되는데 이 객체의 andExpect 메서드에 ResultMatcher를 넘겨줘서 검증한다. ResultMatcher는 아래의 MockMvcResultMatchers가 가지는 static 메서드를 통해서 얻는다.