Package com.google.code.struts2.test.junit

Source Code of com.google.code.struts2.test.junit.StrutsTest

package com.google.code.struts2.test.junit;

import static org.junit.Assert.assertNotNull;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.util.TokenHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.mock.web.MockPageContext;
import org.springframework.mock.web.MockServletContext;

import com.google.code.struts2.test.ProxyExecutionListener;
import com.google.code.struts2.test.TestActionProxy;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;

/**
* some of this code borrowed from struts2 junit plugin
*/
public abstract class StrutsTest<T> implements ProxyExecutionListener {

    /**
     * The token used for the
     * {@link org.apache.struts2.interceptor.TokenInterceptor TokenInterceptor}
     * and/or a
     * {@link org.apache.struts2.interceptor.TokenSessionStoreInterceptor
     * TokenSessionStoreInterceptor}.
     */
    public static final String TEST_TOKEN = "test.token";

    @Rule
    public TestName currentlyExecutingTest = new TestName();
    private T actionFromProxy;
    protected ConfigurationManager configurationManager;
    protected Configuration configuration;
    protected Container container;
    protected ActionProxyFactory actionProxyFactory;
    protected String strutsConfigs;
    protected MockHttpServletResponse response;
    protected MockHttpServletRequest request;
    protected MockPageContext pageContext;
    protected MockServletContext servletContext;
    protected Map<String, String> dispatcherInitParams;
    protected HttpSession httpSession;
    protected Map<String, Object> session;
    protected DefaultResourceLoader resourceLoader = new DefaultResourceLoader();

    /**
     * gets an object from the stack after an action is executed
     */
    protected Object findValueAfterExecute(String key) {
        return ServletActionContext.getValueStack(request).findValue(key);
    }

    /**
     *
     * @return The action object associated with the proxy
     */
    protected T getAction() {
        return this.actionFromProxy;
    }

    @SuppressWarnings("unchecked")
    protected <U> U getAction(Class<U> clazz) {
        return (U) this.actionFromProxy;
    }

    protected boolean containsErrors() {
        Object action = this.getAction();
        if (action instanceof ValidationAware) {
            return ((ValidationAware) action).hasActionErrors();
        }
        throw new UnsupportedOperationException("Current action does not implement ValidationAware interface");
    }

    /**
     * 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
     * FreeMarker, or Velocity (JSPs can be used with the Embedded JSP plugin)
     */
    protected String executeAction(String uri) throws ServletException, UnsupportedEncodingException {
        request.setRequestURI(uri);
        ActionMapping mapping = getActionMapping(request);

        assertNotNull(mapping);
        Dispatcher.getInstance().serviceAction(request, response, servletContext, 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.
     */
    protected ActionProxy getActionProxy(String uri) {

        preProxySetup();

        ActionProxy proxy = getProxy(uri);

        return proxy;
    }

    protected ActionProxy getActionProxy(String multipartName, File file, String actionUri) {
        preProxySetup();
        ActionProxy proxy = this.getProxy(actionUri);
        proxy.getInvocation().getInvocationContext().setParameters(buildMultipartParams(multipartName, file));
        return proxy;
    }

    protected ActionProxy getTokenReadyActionProxy(String multipartName, File file, String actionUri) {
        this.preProxySetup();
        this.setTokens();
        ActionProxy proxy = this.getProxy(actionUri);
        proxy.getInvocation().getInvocationContext().setParameters(buildMultipartParams(multipartName, file));
        return proxy;
    }

    protected Map<String, Object> buildMultipartParams(String multipartName, File file) {

        Map<String, Object> params = new HashMap<String, Object>();
        params.putAll(request.getParameterMap());
        params.put(multipartName, file);
        params.put(multipartName + "FileName", file.getName());
        params.put(multipartName + "ContentType", MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file));
        return params;
    }

    @SuppressWarnings("unchecked")
    private ActionProxy getProxy(String uri) {
        ServletActionContext.setRequest(request);
        request.setRequestURI(uri);
        ActionMapping mapping = getActionMapping(request);
        String namespace = mapping.getNamespace();
        String name = mapping.getName();
        String method = mapping.getMethod();

        ActionProxy proxy = this.actionProxyFactory.createActionProxy(namespace, name, method, new HashMap<String, Object>(), true, false);
        TestActionProxy testProxy = new TestActionProxy(proxy);
        testProxy.addExecutionListener(this);
        this.actionFromProxy = (T) proxy.getAction();
        proxy.setExecuteResult(isExecuteResult());
        ActionContext invocationContext = proxy.getInvocation().getInvocationContext();
        invocationContext.setParameters(new HashMap<String, Object>(request.getParameterMap()));
        invocationContext.setSession(session);
        // set the action context to the one used by the proxy
        ActionContext.setContext(invocationContext);
        ServletActionContext.setServletContext(servletContext);
        ServletActionContext.setRequest(request);
        ServletActionContext.setResponse(response);

        return testProxy;
    }

    /**
     * Uses {@link #getActionProxy(String)} and additional request and session
     * parameters to obtain an ActionProxy that will pass validation by a
     * {@link org.apache.struts2.interceptor.TokenInterceptor TokenInterceptor}
     * and/or a
     * {@link org.apache.struts2.interceptor.TokenSessionStoreInterceptor
     * TokenSessionStoreInterceptor}. <br>
     * <br>
     * <b>Note:</b> Sets token and token name params on request.
     *
     * @param actionPath
     *        The path to the action
     * @return An ActionProxy with valid tokens in its session map
     */
    protected ActionProxy getTokenReadyActionProxy(String uri) {
        this.preProxySetup();
        this.setTokens();
        ActionProxy proxy = getProxy(uri);
        return proxy;
    }

    private void setTokens() {

        /*
         * Add token name and token to request
         */
        request.addParameter(TokenHelper.TOKEN_NAME_FIELD, TokenHelper.DEFAULT_TOKEN_NAME);
        request.addParameter(TokenHelper.DEFAULT_TOKEN_NAME, TEST_TOKEN);

        /*
         * Create session map, add token, and set on proxy context
         */
        session.put(TokenHelper.DEFAULT_TOKEN_NAME, TEST_TOKEN);

    }

    /**
     * Finds an ActionMapping for a given request
     */
    protected ActionMapping getActionMapping(HttpServletRequest request) {
        return container.getInstance(ActionMapper.class).getMapping(request, configurationManager);
    }

    /**
     * Finds an ActionMapping for a given url
     */
    protected ActionMapping getActionMapping(String url) {
        MockHttpServletRequest req = new MockHttpServletRequest();
        req.setRequestURI(url);
        return getActionMapping(req);
    }

    /**
     * Injects dependencies on an Object using Struts internal IoC container
     */
    protected void injectStrutsDependencies(Object object) {
        Dispatcher.getInstance().getContainer().inject(object);
    }

    protected void setupBeforeInitDispatcher() throws Exception {
    }

    protected void initServletMockObjects() {
        servletContext = new MockServletContext(resourceLoader);
        httpSession = new MockHttpSession(servletContext);
        response = new MockHttpServletResponse();
        request = new MockHttpServletRequest(servletContext);
        request.setSession(httpSession);
        pageContext = new MockPageContext(servletContext, request, response);
        session = new SessionMap<String, Object>(request);
    }

    protected void preProxySetup() {
        response = new MockHttpServletResponse();
        pageContext = new MockPageContext(servletContext, request, response);
    }

    /**
     * Sets up the configuration settings, XWork configuration, and message
     * resources
     */
    @Before
    public void setUp() throws Exception {
        processAnnotations(currentlyExecutingTest.getMethodName());
        initServletMockObjects();
        setupBeforeInitDispatcher();
        initDispatcherParams();
        initDispatcher(dispatcherInitParams);
        actionProxyFactory = ((ActionProxyFactory) container.getInstance(ActionProxyFactory.class));
        injectStrutsDependencies(this);
    }

    protected void initDispatcherParams() {
        if (StringUtils.isNotBlank(getConfigPath())) {
            dispatcherInitParams = new HashMap<String, String>();
            dispatcherInitParams.put("config", "struts-default.xml," + getConfigPath());
        }
    }

    protected Dispatcher initDispatcher(Map<String, String> params) {
        Dispatcher du = new Dispatcher(servletContext, params);
        du.init();
        Dispatcher.setInstance(du);
        ValueStack stack = ((ValueStackFactory) du.getContainer().getInstance(ValueStackFactory.class)).createValueStack();
        stack.getContext().put("com.opensymphony.xwork2.ActionContext.container", du.getContainer());
        ActionContext.setContext(new ActionContext(stack.getContext()));
        configurationManager = du.getConfigurationManager();
        configuration = configurationManager.getConfiguration();
        container = configuration.getContainer();
        return du;
    }

    /**
     * Called during dispatcher initialization to obtain a comma-separated list
     * of struts config files to load.
     * <p>
     * If the {@link @StrutsConfiguration} annotation is not used, then this
     * method returns <code>"struts-plugin.xml,struts.xml"</code> by default.
     * <p>
     * If the {@link @StrutsConfiguration} annotation <i>is</i> used, then this
     * method will return a String in the format <code>("struts-plugin.xml," +
     * class-level {@link @StrutsConfiguration} + method-level {@link @StrutsConfiguration})</code>.
     *
     * @return a comma separated list of config locations
     */
    protected String getConfigPath() {
        if (strutsConfigs.equals("")) {
            strutsConfigs = "struts.xml";
        }
        return "struts-plugin.xml," + strutsConfigs;
    }

    @After
    public void tearDown() throws Exception {
        if (configurationManager != null) {
            configurationManager.destroyConfiguration();
            configurationManager = null;
        }
        ActionContext.setContext(null);
        this.configurationManager = null;
        this.configuration = null;
        this.container = null;
        this.actionProxyFactory = null;
        Dispatcher.setInstance(null);
        session = null;
        httpSession = null;
    }

    /**
     * this can be overridden to change the default of the action proxy
     * returned by getActionProxy
     *
     * @return
     */
    protected boolean isExecuteResult() {
        return true;
    }

    protected void processAnnotations(String methodName) throws Exception {
        strutsConfigs = "";
        if (this.getClass().isAnnotationPresent(StrutsConfiguration.class)) {
            StrutsConfiguration classLevelStrutsConfig = this.getClass().getAnnotation(StrutsConfiguration.class);
            strutsConfigs += StringUtil.unsplit(",", classLevelStrutsConfig.locations());
            strutsConfigs += ",";
        }
        Method method = this.getClass().getMethod(methodName);
        if (method.isAnnotationPresent(StrutsConfiguration.class)) {
            StrutsConfiguration strutsConfig = method.getAnnotation(StrutsConfiguration.class);
            strutsConfigs += StringUtil.unsplit(",", strutsConfig.locations());
        }
    }

    /**
     * {@inheritDoc}
     */
    public void afterProxyExecution(ActionInvocation invocation, String result) {
        request = new MockHttpServletRequest(servletContext);
        request.setSession(httpSession);
    }

}
TOP

Related Classes of com.google.code.struts2.test.junit.StrutsTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.