All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mockrunner.servlet.ServletTestModule Maven / Gradle / Ivy

There is a newer version: 2.0.7
Show newest version
package com.mockrunner.servlet;

import javax.servlet.Filter;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

import com.mockrunner.base.HTMLOutputModule;
import com.mockrunner.base.NestedApplicationException;
import com.mockrunner.mock.web.WebMockObjectFactory;

/**
 * Module for servlet and filter tests. Can test
 * single servlets and filters and simulate a filter
 * chain.
 */
public class ServletTestModule extends HTMLOutputModule
{
    private WebMockObjectFactory mockFactory;
    private HttpServlet servlet;
    private boolean doChain;
      
    public ServletTestModule(WebMockObjectFactory mockFactory)
    {
        super(mockFactory);
        this.mockFactory = mockFactory;
        doChain = false;
    }
    
    /**
     * Creates a servlet and initializes it. servletClass must
     * be of the type HttpServlet, otherwise a
     * RuntimeException will be thrown.
     * Sets the specified servlet as the current servlet and
     * initializes the filter chain with it.
     * @param servletClass the class of the servlet
     * @return instance of HttpServlet
     * @throws RuntimeException if servletClass is not an
     *         instance of HttpServlet
     */
    public HttpServlet createServlet(Class servletClass)
    {
        if(!HttpServlet.class.isAssignableFrom(servletClass))
        {
            throw new RuntimeException("servletClass must be an instance of javax.servlet.http.HttpServlet");
        }
        try
        {
            HttpServlet theServlet = (HttpServlet)servletClass.newInstance();
            setServlet(theServlet, true);
            return theServlet;
        }
        catch(Exception exc)
        {
            throw new NestedApplicationException(exc);
        }
    }
    
    /**
     * Sets the specified servlet as the current servlet without initializing it. 
     * You have to set the ServletConfig on your own.
     * Usually you can use 
     * {@link com.mockrunner.mock.web.WebMockObjectFactory#getMockServletConfig}.
     * @param servlet the servlet
     */
    public void setServlet(HttpServlet servlet)
    {
        setServlet(servlet, false);
    }
    
    /**
     * Sets the specified servlet as the current servlet.
     * Initializes it, if doInit is true.
     * @param servlet the servlet
     * @param doInit should init be called
     */
    public void setServlet(HttpServlet servlet, boolean doInit)
    {
        try
        {
	        this.servlet = servlet;
	        if(doInit)
	        {
	            servlet.init(mockFactory.getMockServletConfig());
	        }
	        mockFactory.getMockFilterChain().setServlet(servlet);
        }
        catch(Exception exc)
        {
            throw new NestedApplicationException(exc);
        }
    }
    
    /**
     * Returns the current servlet.
     * @return the servlet
     */
    public HttpServlet getServlet()
    {
        return servlet;
    }
    
    /**
     * Creates a filter, initializes it and adds it to the
     * filter chain. filterClass must be of the type 
     * Filter, otherwise a RuntimeException 
     * will be thrown. You can loop through the filter chain with
     * {@link #doFilter}. If you set doChain to
     * true every call of one of the servlet methods 
     * will go through the filter chain before calling the servlet 
     * method.
     * @param filterClass the class of the filter
     * @return instance of Filter
     * @throws RuntimeException if filterClass is not an
     *         instance of Filter
     */
    public Filter createFilter(Class filterClass)
    {
        if(!Filter.class.isAssignableFrom(filterClass))
        {
            throw new RuntimeException("filterClass must be an instance of javax.servlet.Filter");
        }
        try
        {
            Filter theFilter = (Filter)filterClass.newInstance();
            addFilter(theFilter, true);
            return theFilter;
        }
        catch(Exception exc)
        {
            throw new NestedApplicationException(exc);
        }
    }
    
    /**
     * Adds the specified filter to the filter chain without
     * initializing it. 
     * You have to set the FilterConfig on your own.
     * Usually you can use 
     * {@link com.mockrunner.mock.web.WebMockObjectFactory#getMockFilterConfig}.
     * @param filter the filter
     */
    public void addFilter(Filter filter)
    {
        addFilter(filter, false);
    }
    
    /**
     * Adds the specified filter it to the filter chain. Initializes it,
     * if doInit is true.
     * @param filter the filter
     * @param doInit should init be called
     */
    public void addFilter(Filter filter, boolean doInit)
    {
        if(doInit)
        {
            try
            {
                filter.init(mockFactory.getMockFilterConfig());
            }
            catch(Exception exc)
            {
                throw new NestedApplicationException(exc);
            }
        }
        mockFactory.getMockFilterChain().addFilter(filter);
    }
    
    /**
     * Deletes all filters in the filter chain.
     */
    public void releaseFilters()
    {
        mockFactory.getMockFilterChain().release();
        mockFactory.getMockFilterChain().setServlet(servlet);
    }

    /**
     * If doChain is set to true
     * (default is false) every call of
     * one of the servlet methods will go through the filter chain
     * before calling the servlet method.
     * @param doChain true if the chain should be called
     */
    public void setDoChain(boolean doChain)
    {
        this.doChain = doChain;
    }
    
    /**
     * Loops through the filter chain and calls the current servlets
     * service method at the end (only if a current servlet
     * is set). You can use it to test single filters or the interaction 
     * of filters and servlets.
     * If you set doChain to true (use {@link #setDoChain}),
     * this method is called before any call of a servlet method. If a filter
     * does not call it's chains doFilter method, the chain
     * breaks and the servlet will not be called (just like it in the
     * real container).
     */
    public void doFilter()
    {
        try
        {
            mockFactory.getMockFilterChain().doFilter(mockFactory.getWrappedRequest(), mockFactory.getWrappedResponse());
            mockFactory.getMockFilterChain().reset();
        }
        catch(Exception exc)
        {
            throw new NestedApplicationException(exc);
        }
    }
    
    /**
     * Calls the current servlets init method. Is automatically
     * done when calling {@link #createServlet}.
     */
    public void init()
    {
        try
        {
            servlet.init(mockFactory.getMockServletConfig());
        }
        catch(ServletException exc)
        {
            throw new NestedApplicationException(exc);
        }
    }
    
    /**
     * Calls the current servlets doDelete method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doDelete.
     */
    public void doDelete()
    {
        mockFactory.getMockRequest().setMethod("DELETE");
        callService();
    }
    
    /**
     * Calls the current servlets doGet method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doGet.
     */          
    public void doGet()
    {
        mockFactory.getMockRequest().setMethod("GET");
        callService();
    }
    
    /**
     * Calls the current servlets doOptions method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doOptions.
     */          
    public void doOptions()
    {
        mockFactory.getMockRequest().setMethod("OPTIONS");
        callService();
    }
    
    /**
     * Calls the current servlets doPost method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doPost.
     */         
    public void doPost()
    {
        mockFactory.getMockRequest().setMethod("POST");
        callService();
    }
    
    /**
     * Calls the current servlets doPut method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doPut.
     */         
    public void doPut()
    {
        mockFactory.getMockRequest().setMethod("PUT");
        callService();
    }
    
    /**
     * Calls the current servlets doTrace method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doTrace.
     */          
    public void doTrace()
    {
        mockFactory.getMockRequest().setMethod("TRACE");
        callService();
    }
    
    /**
     * Calls the current servlets doHead method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before doHead.
     */          
    public void doHead()
    {
        mockFactory.getMockRequest().setMethod("HEAD");
        callService();
    }
    
    /**
     * Calls the current servlets service method.
     * If you set doChain to true (use {@link #setDoChain}),
     * the filter chain will be called before service.
     */          
    public void service()
    {
        callService();
    }
    
    /**
     * Returns the last request from the filter chain. Since
     * filters can replace the request with a request wrapper,
     * this method makes only sense after calling at least
     * one filter, i.e. after calling {@link #doFilter} or
     * after calling one servlet method with doChain 
     * set to true.
     * @return the filtered request
     */  
    public ServletRequest getFilteredRequest()
    {
        return mockFactory.getMockFilterChain().getLastRequest();
    }
    
    /**
     * Returns the last response from the filter chain. Since
     * filters can replace the response with a response wrapper,
     * this method makes only sense after calling at least
     * one filter, i.e. after calling {@link #doFilter} or
     * after calling one servlet method with doChain 
     * set to true.
     * @return the filtered response
     */  
    public ServletResponse getFilteredResponse()
    {
        return mockFactory.getMockFilterChain().getLastResponse();
    }
    
    /**
     * Returns the servlet output as a string. Flushes the output
     * before returning it.
     * @return the servlet output
     */
    public String getOutput()
    {
        try
        {
            mockFactory.getMockResponse().getWriter().flush();    
        }
        catch(Exception exc)
        {
            
        }
        return mockFactory.getMockResponse().getOutputStreamContent();
    }
    
    /**
     * Clears the output content
     */ 
    public void clearOutput()
    {
        mockFactory.getMockResponse().resetBuffer();
    }
    
    private void callService()
    {
        try
        {
            if(doChain)
            { 
                doFilter(); 
            }
            else
            {
                servlet.service(mockFactory.getWrappedRequest(), mockFactory.getWrappedResponse());
            }            
        }
        catch(Exception exc)
        {
            throw new NestedApplicationException(exc);
        }
    }  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy