WHY?
프로젝트에서 SpringMVC의 controller를 점점 복잡하게 작성하는 경향이 발생함.(서비스 로직을 웹에서 구현하는 것으로 보임.. )
테스트 코드가 있어야 안전하게 리팩토링이 가능할테니...
springframework이 버전을 올리면서 복잡해지는 것도 있지만 이런 장점들이 계속 쌓여 나가는 것이 마음에 든다.
example
import static org.junit.Assert.*;
import static org.springframework.test.web.ModelAndViewAssert.*;
import org.springframework.mock.web.*;
import org.springframework.web.servlet.*;
import org.springframework.web.servlet.mvc.annotation.*;
import org.springframework.context.*;
import org.codehaus.jettison.json.JSONObject;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/.../xxx.xml" })
public class TistoryTest {
@Inject ApplicationContext applicationContext;
@Inject AnnotationMethodHandlerAdapter handlerAdapter;
@Inject DefaultAnnotationHandlerMapping handlerMapping;
MockHttpServletRequest request;
MockHttpServletResponse response;
/// MockHttpSession session; // if you need session data...
ModelAndView mav;
// 테스트할 spring MVC controller
YourTestController controller;
@Before
public void setUp() throws Exception {
response = new MockHttpServletResponse();
request = new MockHttpServletRequest();
/// session = new MockHttpSession(null);
}
@After
public void tearDown() throws Exception {
/// session.invalidate();
}
// ViewName을 반환하는 일반적인 케이스를 위한 테스트
@Test public void testViewNameReturnMethod () throws Exception{
// [given]
request.setRequestURI("/tistory.do");
request.setMethod("GET");
request.addParameter("method","
viewNameReturnMethod "); // if you using method style
request.addParameter("yourParam","yourValue"); // set parameter
/// saveSession("MYKEY","MYVALUE");
// [when]
handleInterceptor(controller);
handlerAdapter.handle(request, response, controller);
// [then]
assertViewName(mav, "yourViewName"); // check viewname
String attr1 = assertAndReturnModelAttributeOfType(mav,
"yourAttribute1", String.class);
assertEquals(attr1,"expected result");
}
// ajax 통신을 할 경우 직접 ResponseBody에 출력하기 때문에 response의 내용으로 테스트를 수행한다.
@Test public void testJsonReturnMethod() throws Exception{
// [given]
request.setRequestURI("/tistory.do");
request.setMethod("GET");
request.addParameter("method","jsonReturnMethod"); // if you using method style
request.addParameter("yourParam","yourValue"); // set parameter
/// saveSession("MYKEY","MYVALUE");
// [when]
handleInterceptor(controller);
handlerAdapter.handle(request, response, controller);
// [then]
JSONObject json = new JSONObject(response.getContentAsString());
String result = json.getString("your_result_json_key");
assertEquals(result,"expected json value");
}
protected void handleInterceptor(Object controller) throws Exception {
for (final HandlerInterceptor interceptor : handlerMapping.getHandler(
request).getInterceptors()) {
interceptor.preHandle(request, response, controller);
}
}
/* protected void saveSession(String key, Object value) {
session.putValue(key, value);
request.setSession(session);
} */
}
[주의사항]
session scoped bean을 사용할 경우 다음 에러가 발생함 :
java.lang.IllegalStateException: No Scope registered for scope 'session'
아래 참고자료를 이용하여 해결할 것.
ref : http://blog.solidcraft.eu/2011/04/how-to-test-spring-session-scoped-beans.html