Repository: struts Updated Branches: refs/heads/master f829e01f6 -> 18fc7eb15
WW-4549 - Extend Struts Test Case to support tests for REST plugin actions Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/18fc7eb1 Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/18fc7eb1 Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/18fc7eb1 Branch: refs/heads/master Commit: 18fc7eb155935a5358c00cfa8f5befcacd4bf4db Parents: f829e01 Author: Johannes Geppert <jo...@apache.org> Authored: Tue Sep 22 18:18:55 2015 +0200 Committer: Johannes Geppert <jo...@apache.org> Committed: Tue Sep 22 18:18:55 2015 +0200 ---------------------------------------------------------------------- .../struts2/ConventionPluginResourceLoader.java | 29 ++++ .../apache/struts2/StrutsJUnit4TestCase.java | 7 +- .../org/apache/struts2/StrutsRestTestCase.java | 131 +++++++++++++++++++ 3 files changed, 165 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/18fc7eb1/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java ---------------------------------------------------------------------- diff --git a/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java b/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java new file mode 100644 index 0000000..fb94d27 --- /dev/null +++ b/plugins/junit/src/main/java/org/apache/struts2/ConventionPluginResourceLoader.java @@ -0,0 +1,29 @@ +package org.apache.struts2; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; + +import java.net.URL; + +public class ConventionPluginResourceLoader extends DefaultResourceLoader { + + private static final Logger log = LogManager.getLogger(ConventionPluginResourceLoader.class); + + @Override + public Resource getResource(String location) { + if (StringUtils.startsWith(location, "/WEB-INF/")) { + try { + URL url = new URL("file:/" + System.getProperty("user.dir") + "/src/main/webapp" + location); + return new UrlResource(url); + } catch (Exception e) { + log.error("Error occurred during get resource for location: {}", location, e); + } + } + + return super.getResource(location); + } +} http://git-wip-us.apache.org/repos/asf/struts/blob/18fc7eb1/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java ---------------------------------------------------------------------- diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java b/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java index 20ec81c..f0ab857 100644 --- a/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java +++ b/plugins/junit/src/main/java/org/apache/struts2/StrutsJUnit4TestCase.java @@ -21,7 +21,10 @@ package org.apache.struts2; -import com.opensymphony.xwork2.*; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionProxy; +import com.opensymphony.xwork2.ActionProxyFactory; +import com.opensymphony.xwork2.XWorkJUnit4TestCase; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.interceptor.ValidationAware; import com.opensymphony.xwork2.interceptor.annotations.After; @@ -159,7 +162,7 @@ public abstract class StrutsJUnit4TestCase<T> extends XWorkJUnit4TestCase { // set the action context to the one used by the proxy ActionContext.setContext(invocationContext); - // this is normaly done in onSetUp(), but we are using Struts internal + // this is normally done in onSetUp(), but we are using Struts internal // objects (proxy and action invocation) // so we have to hack around so it works ServletActionContext.setServletContext(servletContext); http://git-wip-us.apache.org/repos/asf/struts/blob/18fc7eb1/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java ---------------------------------------------------------------------- diff --git a/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java b/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java new file mode 100644 index 0000000..9292366 --- /dev/null +++ b/plugins/junit/src/main/java/org/apache/struts2/StrutsRestTestCase.java @@ -0,0 +1,131 @@ +package org.apache.struts2; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionProxy; +import com.opensymphony.xwork2.ActionProxyFactory; +import com.opensymphony.xwork2.config.Configuration; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockPageContext; +import org.springframework.mock.web.MockServletContext; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; + +import static org.junit.Assert.assertNotNull; + +public class StrutsRestTestCase<T> extends StrutsJUnit4TestCase<T> { + + /** + * Executes an action and returns it's output (not the result returned from + * execute()), but the actual output that would be written to the response. + * For this to work the configured result for the action needs to be JSON, + * FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin) + * + * @param uri action uri to test + * @return execution result + * + * @throws ServletException in case of servlet errors + * @throws UnsupportedEncodingException in case of unsupported encoding + */ + @Override + protected String executeAction(String uri) throws ServletException, UnsupportedEncodingException { + return executeAction("GET", uri); + } + + /** + * Executes an action and returns it's output (not the result returned from + * execute()), but the actual output that would be written to the response. + * For this to work the configured result for the action needs to be JSON, + * FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin) + * + * @param httpMethod HTTP method of request like GET, POST, PUT or DELETE + * @param uri action uri to test + * @return execution result + * + * @throws ServletException in case of servlet errors + * @throws UnsupportedEncodingException in case of unsupported encoding + */ + protected String executeAction(String httpMethod, String uri) throws ServletException, UnsupportedEncodingException { + request.setRequestURI(uri); + request.setMethod(httpMethod); + + ActionMapping mapping = getActionMapping(request); + + assertNotNull(mapping); + Dispatcher.getInstance().serviceAction(request, response, mapping); + + if (response.getStatus() != HttpServletResponse.SC_OK) + throw new ServletException("Error code [" + response.getStatus() + "], Error: [" + + response.getErrorMessage() + "]"); + + return response.getContentAsString(); + } + + + /** + * Creates an action proxy for a request, and sets parameters of the ActionInvocation to the passed + * parameters. Make sure to set the request parameters in the protected "request" object before calling this method. + * + * @param uri request uri to test + * @return action proxy found for this request uri + */ + @Override + protected ActionProxy getActionProxy(String uri) { + return getActionProxy("GET", uri); + } + + /** + * Creates an action proxy for a request, and sets parameters of the ActionInvocation to the passed + * parameters. Make sure to set the request parameters in the protected "request" object before calling this method. + * + * @param httpMethod HTTP method of request like GET, POST, PUT or DELETE + * @param uri request uri to test + * @return action proxy found for this request uri + */ + protected ActionProxy getActionProxy(String httpMethod, String uri) { + request.setRequestURI(uri); + request.setMethod(httpMethod); + + ActionMapping mapping = getActionMapping(request); + String namespace = mapping.getNamespace(); + String name = mapping.getName(); + String method = mapping.getMethod(); + + Configuration config = configurationManager.getConfiguration(); + ActionProxy proxy = config.getContainer() + .getInstance(ActionProxyFactory.class) + .createActionProxy(namespace, name, method, new HashMap<String, Object>(), true, false); + + ActionContext invocationContext = proxy.getInvocation().getInvocationContext(); + invocationContext.getContextMap().put(ServletActionContext.ACTION_MAPPING, mapping); + invocationContext.setParameters(new HashMap<String, Object>(request.getParameterMap())); + // set the action context to the one used by the proxy + ActionContext.setContext(invocationContext); + + // set the action context to the one used by the proxy + ActionContext.setContext(invocationContext); + + // this is normally done in onSetUp(), but we are using Struts internal + // objects (proxy and action invocation) + // so we have to hack around so it works + ServletActionContext.setServletContext(servletContext); + ServletActionContext.setRequest(request); + ServletActionContext.setResponse(response); + + return proxy; + } + + @Override + protected void initServletMockObjects() { + servletContext = new MockServletContext(resourceLoader); + response = new MockHttpServletResponse(); + request = new MockHttpServletRequest(); + pageContext = new MockPageContext(servletContext, request, response); + resourceLoader = new ConventionPluginResourceLoader(); + } +}