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();
}

 

+ Recent posts