Scenario
MockMVC를 활용하여 벤더사 Param을 위해 만든 MessageConverter를 테스트 하려고 하였다.
Meesage Converter를 Junit에서는 Test하였을때 잘 동작하였는데, 막상 Spring application 에서는 잘 동작하지 않았다. 그 이유는 원래 HttpServletRequest에서는 inputstream을 한번밖에 읽을 수 없지만, MockHttpServletRequest 에서는 getInputStream을 할때마다 Byte[]를 만들어서 준다.
그래서 실제 스프링 환경과 똑같이 단위테스트를 하기위해 NotReuseHttpServletRequest을 만들게 되었다.
Solution
1. 먼저, Junit의 RequestBuilder을 Delegate 하기위해 만든 NotReuseMockHttpServletRequestBuilder가 존재한다.
public class NotReuseMockHttpServletRequestBuilder implements RequestBuilder{
private RequestBuilder requestBuilder;
public NotReuseMockHttpServletRequestBuilder(RequestBuilder requestBuilder) {
this.requestBuilder = requestBuilder;
}
@Override
public MockHttpServletRequest buildRequest(ServletContext servletContext) {
MockHttpServletRequest buildRequest = this.requestBuilder.buildRequest(servletContext);
return new NotReuseHttpServletRequest(buildRequest);
}
}
2.다음으로 실질적으로 MockHttpServletRequest 리턴하는 NotReuseHttpServletRequestNotReuseHttpServletRequest 클래스가 존재한다.
Java 11.83 KB
/**
* Movck MVC 테스트시에 실제 Spring MVC 환경과 똑같이
* InputStream을 두번 읽지 못하도록 테스트하기위한 클래스
*/
class NotReuseHttpServletRequest extends MockHttpServletRequest {
private MockHttpServletRequest buildRequest;
private ServletInputStream servletInputStream;
public NotReuseHttpServletRequest(MockHttpServletRequest buildRequest) {
this.buildRequest = buildRequest;
}
public ServletInputStream getInputStream() {
if(this.servletInputStream == null) {
this.servletInputStream = this.buildRequest.getInputStream();
}
return this.servletInputStream;
}
public int hashCode() {
return buildRequest.hashCode();
}
public boolean equals(Object obj) {
return buildRequest.equals(obj);
}
public ServletContext getServletContext() {
return buildRequest.getServletContext();
}
public boolean isActive() {
return buildRequest.isActive();
}
public void close() {
buildRequest.close();
}
public void invalidate() {
buildRequest.invalidate();
}
public String toString() {
return buildRequest.toString();
}
public Object getAttribute(String name) {
return buildRequest.getAttribute(name);
}
public Enumeration<String> getAttributeNames() {
return buildRequest.getAttributeNames();
}
public String getCharacterEncoding() {
return buildRequest.getCharacterEncoding();
}
public void setCharacterEncoding(String characterEncoding) {
buildRequest.setCharacterEncoding(characterEncoding);
}
public void setContent(byte[] content) {
buildRequest.setContent(content);
}
public int getContentLength() {
return buildRequest.getContentLength();
}
public long getContentLengthLong() {
return buildRequest.getContentLengthLong();
}
public void setContentType(String contentType) {
buildRequest.setContentType(contentType);
}
public String getContentType() {
return buildRequest.getContentType();
}
public void setParameter(String name, String value) {
buildRequest.setParameter(name, value);
}
public void setParameter(String name, String[] values) {
buildRequest.setParameter(name, values);
}
public void setParameters(Map params) {
buildRequest.setParameters(params);
}
public void addParameter(String name, String value) {
buildRequest.addParameter(name, value);
}
public void addParameter(String name, String[] values) {
buildRequest.addParameter(name, values);
}
public void addParameters(Map params) {
buildRequest.addParameters(params);
}
public void removeParameter(String name) {
buildRequest.removeParameter(name);
}
public void removeAllParameters() {
buildRequest.removeAllParameters();
}
public String getParameter(String name) {
return buildRequest.getParameter(name);
}
public Enumeration<String> getParameterNames() {
return buildRequest.getParameterNames();
}
public String[] getParameterValues(String name) {
return buildRequest.getParameterValues(name);
}
public Map<String, String[]> getParameterMap() {
return buildRequest.getParameterMap();
}
public void setProtocol(String protocol) {
buildRequest.setProtocol(protocol);
}
public String getProtocol() {
return buildRequest.getProtocol();
}
public void setScheme(String scheme) {
buildRequest.setScheme(scheme);
}
public String getScheme() {
return buildRequest.getScheme();
}
public void setServerName(String serverName) {
buildRequest.setServerName(serverName);
}
public String getServerName() {
return buildRequest.getServerName();
}
public void setServerPort(int serverPort) {
buildRequest.setServerPort(serverPort);
}
public int getServerPort() {
return buildRequest.getServerPort();
}
public BufferedReader getReader() throws UnsupportedEncodingException {
return buildRequest.getReader();
}
public void setRemoteAddr(String remoteAddr) {
buildRequest.setRemoteAddr(remoteAddr);
}
public String getRemoteAddr() {
return buildRequest.getRemoteAddr();
}
public void setRemoteHost(String remoteHost) {
buildRequest.setRemoteHost(remoteHost);
}
public String getRemoteHost() {
return buildRequest.getRemoteHost();
}
public void setAttribute(String name, Object value) {
buildRequest.setAttribute(name, value);
}
public void removeAttribute(String name) {
buildRequest.removeAttribute(name);
}
public void clearAttributes() {
buildRequest.clearAttributes();
}
public void addPreferredLocale(Locale locale) {
buildRequest.addPreferredLocale(locale);
}
public void setPreferredLocales(List<Locale> locales) {
buildRequest.setPreferredLocales(locales);
}
public Locale getLocale() {
return buildRequest.getLocale();
}
public Enumeration<Locale> getLocales() {
return buildRequest.getLocales();
}
public void setSecure(boolean secure) {
buildRequest.setSecure(secure);
}
public boolean isSecure() {
return buildRequest.isSecure();
}
public RequestDispatcher getRequestDispatcher(String path) {
return buildRequest.getRequestDispatcher(path);
}
public String getRealPath(String path) {
return buildRequest.getRealPath(path);
}
public void setRemotePort(int remotePort) {
buildRequest.setRemotePort(remotePort);
}
public int getRemotePort() {
return buildRequest.getRemotePort();
}
public void setLocalName(String localName) {
buildRequest.setLocalName(localName);
}
public String getLocalName() {
return buildRequest.getLocalName();
}
public void setLocalAddr(String localAddr) {
buildRequest.setLocalAddr(localAddr);
}
public String getLocalAddr() {
return buildRequest.getLocalAddr();
}
public void setLocalPort(int localPort) {
buildRequest.setLocalPort(localPort);
}
public int getLocalPort() {
return buildRequest.getLocalPort();
}
public AsyncContext startAsync() {
return buildRequest.startAsync();
}
public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
return buildRequest.startAsync(request, response);
}
public void setAsyncStarted(boolean asyncStarted) {
buildRequest.setAsyncStarted(asyncStarted);
}
public boolean isAsyncStarted() {
return buildRequest.isAsyncStarted();
}
public void setAsyncSupported(boolean asyncSupported) {
buildRequest.setAsyncSupported(asyncSupported);
}
public boolean isAsyncSupported() {
return buildRequest.isAsyncSupported();
}
public void setAsyncContext(MockAsyncContext asyncContext) {
buildRequest.setAsyncContext(asyncContext);
}
public AsyncContext getAsyncContext() {
return buildRequest.getAsyncContext();
}
public void setDispatcherType(DispatcherType dispatcherType) {
buildRequest.setDispatcherType(dispatcherType);
}
public DispatcherType getDispatcherType() {
return buildRequest.getDispatcherType();
}
public void setAuthType(String authType) {
buildRequest.setAuthType(authType);
}
public String getAuthType() {
return buildRequest.getAuthType();
}
public void setCookies(Cookie... cookies) {
buildRequest.setCookies(cookies);
}
public Cookie[] getCookies() {
return buildRequest.getCookies();
}
public void addHeader(String name, Object value) {
buildRequest.addHeader(name, value);
}
public long getDateHeader(String name) {
return buildRequest.getDateHeader(name);
}
public String getHeader(String name) {
return buildRequest.getHeader(name);
}
public Enumeration<String> getHeaders(String name) {
return buildRequest.getHeaders(name);
}
public Enumeration<String> getHeaderNames() {
return buildRequest.getHeaderNames();
}
public int getIntHeader(String name) {
return buildRequest.getIntHeader(name);
}
public void setMethod(String method) {
buildRequest.setMethod(method);
}
public String getMethod() {
return buildRequest.getMethod();
}
public void setPathInfo(String pathInfo) {
buildRequest.setPathInfo(pathInfo);
}
public String getPathInfo() {
return buildRequest.getPathInfo();
}
public String getPathTranslated() {
return buildRequest.getPathTranslated();
}
public void setContextPath(String contextPath) {
buildRequest.setContextPath(contextPath);
}
public String getContextPath() {
return buildRequest.getContextPath();
}
public void setQueryString(String queryString) {
buildRequest.setQueryString(queryString);
}
public String getQueryString() {
return buildRequest.getQueryString();
}
public void setRemoteUser(String remoteUser) {
buildRequest.setRemoteUser(remoteUser);
}
public String getRemoteUser() {
return buildRequest.getRemoteUser();
}
public void addUserRole(String role) {
buildRequest.addUserRole(role);
}
public boolean isUserInRole(String role) {
return buildRequest.isUserInRole(role);
}
public void setUserPrincipal(Principal userPrincipal) {
buildRequest.setUserPrincipal(userPrincipal);
}
public Principal getUserPrincipal() {
return buildRequest.getUserPrincipal();
}
public void setRequestedSessionId(String requestedSessionId) {
buildRequest.setRequestedSessionId(requestedSessionId);
}
public String getRequestedSessionId() {
return buildRequest.getRequestedSessionId();
}
public void setRequestURI(String requestURI) {
buildRequest.setRequestURI(requestURI);
}
public String getRequestURI() {
return buildRequest.getRequestURI();
}
public StringBuffer getRequestURL() {
return buildRequest.getRequestURL();
}
public void setServletPath(String servletPath) {
buildRequest.setServletPath(servletPath);
}
public String getServletPath() {
return buildRequest.getServletPath();
}
public void setSession(HttpSession session) {
buildRequest.setSession(session);
}
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
return buildRequest.upgrade(handlerClass);
}
public HttpSession getSession(boolean create) {
return buildRequest.getSession(create);
}
public HttpSession getSession() {
return buildRequest.getSession();
}
public String changeSessionId() {
return buildRequest.changeSessionId();
}
public void setRequestedSessionIdValid(boolean requestedSessionIdValid) {
buildRequest.setRequestedSessionIdValid(requestedSessionIdValid);
}
public boolean isRequestedSessionIdValid() {
return buildRequest.isRequestedSessionIdValid();
}
public void setRequestedSessionIdFromCookie(boolean requestedSessionIdFromCookie) {
buildRequest.setRequestedSessionIdFromCookie(requestedSessionIdFromCookie);
}
public boolean isRequestedSessionIdFromCookie() {
return buildRequest.isRequestedSessionIdFromCookie();
}
public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL) {
buildRequest.setRequestedSessionIdFromURL(requestedSessionIdFromURL);
}
public boolean isRequestedSessionIdFromURL() {
return buildRequest.isRequestedSessionIdFromURL();
}
public boolean isRequestedSessionIdFromUrl() {
return buildRequest.isRequestedSessionIdFromUrl();
}
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
return buildRequest.authenticate(response);
}
public void login(String username, String password) throws ServletException {
buildRequest.login(username, password);
}
public void logout() throws ServletException {
buildRequest.logout();
}
public void addPart(Part part) {
buildRequest.addPart(part);
}
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
return buildRequest.getPart(name);
}
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
return buildRequest.getParts();
}
}
3.실질적인 사용법은 다음과 같다.
@Test
public void example() throws Exception {
logger.debug("############# Post Test #################");
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.post("/test")
.contentType(MediaType.TEXT_XML)
.content(content);
//Spring MVC에서는 스트림을 한번 읽으면 Flush되나 MockMVC에서는 Stream을 Reuse를 할 수 있으므로
//실제 Spring MVC와 똑같이 Reuse 할 수 없게 하기위해서 delegator를 만들었다.
NotReuseMockHttpServletRequestBuilder delegator = new NotReuseMockHttpServletRequestBuilder(builder);
MvcResult result = mockMvc.perform(delegator).andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
'To be Developer > Spring' 카테고리의 다른 글
[Spring] X-Frame-Options 문제 및 ViewResolver 설정 (0) | 2019.07.18 |
---|---|
DispatcherServlet 에서 url-pattern 속성의 의미와 사용법 (1) | 2019.04.11 |
WebAplicationContext 란? (1) | 2018.05.17 |
[AOP]Root Aplication Context, Servlet Context 그리고 AOP (0) | 2018.04.06 |
[Spring]Container의 관계 (0) | 2017.09.19 |