Spring Test MVC로 컨트롤러 테스트하기

기본

기선이 형의 Spring Test MVC 프로젝트 소개글을 보고 언제 한 번 써봐야겠다 하다가 요새 좀 살펴보고 있습니다.

사실 고백하자면 컨트롤러 테스트 케이스는 작성 해본적이 거의 없는데요.. 이거 테스트 작성할 시간에 그냥 브라우저로 돌려보는게 낫겠다 싶어서요. 그러다가 요새 Spring Test MVC를 써보니 테스트 하기도 쉽고 또 상당히 재미있네요 ㅎㅎ

Maven 디펜던시

아직 정식 릴리즈가 안돼서 메이븐 레파지토리를 추가해 줘야 합니다:

<repository>
	<id>spring-snapshot</id>
	<name>Spring Maven SNAPSHOT Repository</name>
	<url>http://repo.springsource.org/libs-snapshot</url>
</repository>

그리고 디펜던시도 추가해 줘야겠죠:

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-test-mvc</artifactId>
	<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>

몇 가지 샘플코드

Spring Test MVC는 빌더 패턴 형태로 테스트 템플릿을 만들고 세부적인 것은 다양한 Matchers를 통해 만들어 나가는 식으로 구성됩니다. hamcrest랑 비슷하게요. (그러고보니 hamcrest Matchers를 바로 사용할 수 있는 부분도 본 것 같습니다)
org.springframework.test.web.server.result 패키지를 확인해보면 다양한 Matcher를 볼 수 있죠. 이걸 쓰려고 전부 static import 할 필요는 없고, 다음 2개 클래스만 static import 해줍니다:

import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;

Spring MVC의 컨트롤러를 테스트 하기 위해선 먼저 스프링 컨텍스트가 필요한데요. 예전 같았으면 @RunWith, @ContextConfiguration 어노테이션을 붙여서 시작했겠지만 Spring Test MVC는 MockMvcBuilders 클래스를 사용합니다:

MockMvc mockMvc = MockMvcBuilders.xmlConfigSetup(new String[] {"classpath:/applicationContext.xml", "file:web/WEB-INF/spring-servlet.xml"}).build();

XML을 사용하는 방법 외에 @Configuration, WebApplicationContext, 단일 Controller를 사용해 테스트 컨텍스트를 꾸리는 방법도 있습니다. MockMvc를 생성했으면 테스트 할 URL과 파라미터 등을 세팅하면 됩니다:

mockMvc.perform(post("/message/post").param("author", "mOer").param("body", "some contents...").param("title", "some title"))
.andExpect(status().isOk())
.andExpect(redirectedUrl("/list"));</code>

앞에서 static import를 한 이유는 perform() 메소드에 사용하는 get(), post() 등의 메소드가 MockMvcRequestBuilders 클래스에 정의돼 있기 때문입니다. 반대로 다른 Matchers 클래스를 static import 할 필요가 없는 이유는 MockMvcRequestBuilders 클래스 정의된 각각의 메소드가 빌더 형태로 만들어져 있어서 각각의 필요한 Matchers 인스턴스를 리턴하기 때문입니다.

MockMvcResultMatchers 클래스에는 해당 컨트롤러를 호출한 뒤 다양한 검사를 할 수 있는 static 메소드가 정의돼 있습니다.

andExpect() 메소드를 통해서 Assertion을 할 수 있기 때문에 구지 Assert.. 메소드들을 사용할 필요가 없습니다. 또한 andReturn() 메소드를 호출하면 MvcResult가 리턴되는데, 이 안에 ModelAndView 객체가 있어서 실질적으로 어떤 모델이 뷰에 리턴되는지 검증 할 수도 있습니다. 물론, andExpect() 에서도 할 수 있구요:

.andExpect(model().attributeExists("message"));

@PathVariable을 사용하는 것도 문제 없습니다. 만약 @RequestMapping(“/delete/{messageId}”) 이렇게 매핑된 컨트롤러가 있다면, /delete/125 이렇게 테스트 할 수도 있겠지만 그대로 URI Template을 사용하는 방법도 제공해 줍니다:

mockMvc.perform(request(HttpMethod.GET, "/message/delete/{messageId}", 125))

헐.. 테스트하기 엄청 편해요. Spring Test MVC 프로젝트가 아직 정식 릴리즈는 안됐지만 기선이 형 포스팅에는 공식 프로젝트와 합쳐질 거란 말도 있더라구요. 이상 @MVC 테스트의 끝판왕인 Spring Test MVC의 간단한 소개 였습니다 ㅋ