com.mockrunner.servlet.ServletTestModule Maven / Gradle / Ivy
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);
}
}
}