Support Filters/Servlet invocation in MockFilterChain

This commit adds the ability to allow the MockFilterChain to invoke
a List of Filter's and/or a Servlet.

Issue: SPR-9745
This commit is contained in:
Rob Winch 2012-08-31 12:59:26 -05:00 committed by Rossen Stoyanchev
parent 6bce098310
commit c92a06f003
5 changed files with 558 additions and 12 deletions

View File

@ -16,11 +16,20 @@
package org.springframework.mock.web;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@ -29,6 +38,8 @@ import org.springframework.util.Assert;
* custom {@link javax.servlet.Filter} implementations.
*
* @author Juergen Hoeller
* @author Rob Winch
*
* @since 2.0.3
* @see MockFilterConfig
* @see PassThroughFilterChain
@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
private ServletResponse response;
private final Iterator<Filter> iterator;
/**
* Records the request and response.
* Register a single do-nothing {@link Filter} implementation. The first
* invocation saves the request and response. Subsequent invocations raise
* an {@link IllegalStateException}.
*/
public void doFilter(ServletRequest request, ServletResponse response) {
public MockFilterChain() {
this.iterator = null;
}
/**
* Create a FilterChain with a {@link Servlet} but without filters.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet) {
this(new ServletFilterProxy(servlet));
}
/**
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet, Filter... filters) {
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
}
/**
* Create a {@link FilterChain} with one or more {@link Filter} instances.
*
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
private MockFilterChain(Filter... filters) {
Assert.notNull(filters, "filters cannot be null");
Assert.notEmpty(filters, "filters cannot be empty");
Assert.noNullElements(filters, "filters cannot contain null values");
this.iterator = Arrays.asList(filters).iterator();
}
/**
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
* request and response.
*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
throw new IllegalStateException("This FilterChain has already been called!");
}
if ((this.iterator != null) && (this.iterator.hasNext())) {
Filter nextFilter = this.iterator.next();
nextFilter.doFilter(request, response, this);
}
this.request = request;
this.response = response;
}
@ -67,4 +131,35 @@ public class MockFilterChain implements FilterChain {
return this.response;
}
/**
* A filter that simply delegates to a Servlet.
*/
private static class ServletFilterProxy implements Filter {
private final Servlet delegateServlet;
private ServletFilterProxy(Servlet servlet) {
Assert.notNull(servlet, "servlet cannot be null");
this.delegateServlet = servlet;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.delegateServlet.service(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
@Override
public String toString() {
return this.delegateServlet.toString();
}
}
}

View File

@ -16,11 +16,20 @@
package org.springframework.mock.web;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@ -29,6 +38,8 @@ import org.springframework.util.Assert;
* custom {@link javax.servlet.Filter} implementations.
*
* @author Juergen Hoeller
* @author Rob Winch
*
* @since 2.0.3
* @see MockFilterConfig
* @see PassThroughFilterChain
@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
private ServletResponse response;
private final Iterator<Filter> iterator;
/**
* Records the request and response.
* Register a single do-nothing {@link Filter} implementation. The first
* invocation saves the request and response. Subsequent invocations raise
* an {@link IllegalStateException}.
*/
public void doFilter(ServletRequest request, ServletResponse response) {
public MockFilterChain() {
this.iterator = null;
}
/**
* Create a FilterChain with a {@link Servlet} but without filters.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet) {
this(new ServletFilterProxy(servlet));
}
/**
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet, Filter... filters) {
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
}
/**
* Create a {@link FilterChain} with one or more {@link Filter} instances.
*
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
private MockFilterChain(Filter... filters) {
Assert.notNull(filters, "filters cannot be null");
Assert.notEmpty(filters, "filters cannot be empty");
Assert.noNullElements(filters, "filters cannot contain null values");
this.iterator = Arrays.asList(filters).iterator();
}
/**
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
* request and response.
*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
throw new IllegalStateException("This FilterChain has already been called!");
}
if ((this.iterator != null) && (this.iterator.hasNext())) {
Filter nextFilter = this.iterator.next();
nextFilter.doFilter(request, response, this);
}
this.request = request;
this.response = response;
}
@ -67,4 +131,35 @@ public class MockFilterChain implements FilterChain {
return this.response;
}
/**
* A filter that simply delegates to a Servlet.
*/
private static class ServletFilterProxy implements Filter {
private final Servlet delegateServlet;
private ServletFilterProxy(Servlet servlet) {
Assert.notNull(servlet, "servlet cannot be null");
this.delegateServlet = servlet;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.delegateServlet.service(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
@Override
public String toString() {
return this.delegateServlet.toString();
}
}
}

View File

@ -0,0 +1,166 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.mock.web;
import static org.easymock.EasyMock.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.junit.Before;
import org.junit.Test;
/**
* Test fixture for {@link MockFilterChain}.
*
* @author Rob Winch
*/
public class MockFilterChainTests {
private ServletRequest request;
private ServletResponse response;
@Before
public void setup() {
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
}
@Test(expected=IllegalArgumentException.class)
public void constructorNullServlet() {
new MockFilterChain((Servlet) null);
}
@Test(expected=IllegalArgumentException.class)
public void constructorNullFilter() {
new MockFilterChain(createMock(Servlet.class), (Filter) null);
}
@Test(expected = IllegalArgumentException.class)
public void doFilterNullRequest() throws Exception {
MockFilterChain chain = new MockFilterChain();
chain.doFilter(null, this.response);
}
@Test(expected = IllegalArgumentException.class)
public void doFilterNullResponse() throws Exception {
MockFilterChain chain = new MockFilterChain();
chain.doFilter(this.request, null);
}
@Test
public void doFilterEmptyChain() throws Exception {
MockFilterChain chain = new MockFilterChain();
chain.doFilter(this.request, this.response);
assertThat(chain.getRequest(), is(request));
assertThat(chain.getResponse(), is(response));
try {
chain.doFilter(this.request, this.response);
fail("Expected Exception");
}
catch(IllegalStateException ex) {
assertEquals("This FilterChain has already been called!", ex.getMessage());
}
}
@Test
public void doFilterWithServlet() throws Exception {
Servlet servlet = createMock(Servlet.class);
MockFilterChain chain = new MockFilterChain(servlet);
servlet.service(this.request, this.response);
replay(servlet);
chain.doFilter(this.request, this.response);
verify(servlet);
try {
chain.doFilter(this.request, this.response);
fail("Expected Exception");
}
catch(IllegalStateException ex) {
assertEquals("This FilterChain has already been called!", ex.getMessage());
}
}
@Test
public void doFilterWithServletAndFilters() throws Exception {
Servlet servlet = createMock(Servlet.class);
servlet.service(this.request, this.response);
replay(servlet);
MockFilter filter2 = new MockFilter(servlet);
MockFilter filter1 = new MockFilter(null);
MockFilterChain chain = new MockFilterChain(servlet, filter1, filter2);
chain.doFilter(this.request, this.response);
assertTrue(filter1.invoked);
assertTrue(filter2.invoked);
verify(servlet);
try {
chain.doFilter(this.request, this.response);
fail("Expected Exception");
}
catch(IllegalStateException ex) {
assertEquals("This FilterChain has already been called!", ex.getMessage());
}
}
private static class MockFilter implements Filter {
private final Servlet servlet;
private boolean invoked;
public MockFilter(Servlet servlet) {
this.servlet = servlet;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.invoked = true;
if (this.servlet != null) {
this.servlet.service(request, response);
}
else {
chain.doFilter(request, response);
}
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
}
}

View File

@ -16,11 +16,20 @@
package org.springframework.mock.web;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@ -29,6 +38,8 @@ import org.springframework.util.Assert;
* custom {@link javax.servlet.Filter} implementations.
*
* @author Juergen Hoeller
* @author Rob Winch
*
* @since 2.0.3
* @see MockFilterConfig
* @see PassThroughFilterChain
@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
private ServletResponse response;
private final Iterator<Filter> iterator;
/**
* Records the request and response.
* Register a single do-nothing {@link Filter} implementation. The first
* invocation saves the request and response. Subsequent invocations raise
* an {@link IllegalStateException}.
*/
public void doFilter(ServletRequest request, ServletResponse response) {
public MockFilterChain() {
this.iterator = null;
}
/**
* Create a FilterChain with a {@link Servlet} but without filters.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet) {
this(new ServletFilterProxy(servlet));
}
/**
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet, Filter... filters) {
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
}
/**
* Create a {@link FilterChain} with one or more {@link Filter} instances.
*
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
private MockFilterChain(Filter... filters) {
Assert.notNull(filters, "filters cannot be null");
Assert.notEmpty(filters, "filters cannot be empty");
Assert.noNullElements(filters, "filters cannot contain null values");
this.iterator = Arrays.asList(filters).iterator();
}
/**
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
* request and response.
*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
throw new IllegalStateException("This FilterChain has already been called!");
}
if ((this.iterator != null) && (this.iterator.hasNext())) {
Filter nextFilter = this.iterator.next();
nextFilter.doFilter(request, response, this);
}
this.request = request;
this.response = response;
}
@ -67,4 +131,35 @@ public class MockFilterChain implements FilterChain {
return this.response;
}
/**
* A filter that simply delegates to a Servlet.
*/
private static class ServletFilterProxy implements Filter {
private final Servlet delegateServlet;
private ServletFilterProxy(Servlet servlet) {
Assert.notNull(servlet, "servlet cannot be null");
this.delegateServlet = servlet;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.delegateServlet.service(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
@Override
public String toString() {
return this.delegateServlet.toString();
}
}
}

View File

@ -16,11 +16,20 @@
package org.springframework.mock.web;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Mock implementation of the {@link javax.servlet.FilterChain} interface.
@ -29,6 +38,8 @@ import org.springframework.util.Assert;
* custom {@link javax.servlet.Filter} implementations.
*
* @author Juergen Hoeller
* @author Rob Winch
*
* @since 2.0.3
* @see MockFilterConfig
* @see PassThroughFilterChain
@ -39,16 +50,69 @@ public class MockFilterChain implements FilterChain {
private ServletResponse response;
private final Iterator<Filter> iterator;
/**
* Records the request and response.
* Register a single do-nothing {@link Filter} implementation. The first
* invocation saves the request and response. Subsequent invocations raise
* an {@link IllegalStateException}.
*/
public void doFilter(ServletRequest request, ServletResponse response) {
public MockFilterChain() {
this.iterator = null;
}
/**
* Create a FilterChain with a {@link Servlet} but without filters.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet) {
this(new ServletFilterProxy(servlet));
}
/**
* Create a FilterChain with one or more {@link Filter} instances and a {@link Servlet}.
*
* @param servlet the {@link Servlet} to use in this {@link FilterChain}
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
public MockFilterChain(Servlet servlet, Filter... filters) {
this(ObjectUtils.addObjectToArray(filters, new ServletFilterProxy(servlet)));
}
/**
* Create a {@link FilterChain} with one or more {@link Filter} instances.
*
* @param filters the {@link Filter}'s to use in this {@link FilterChain}
* @since 3.2
*/
private MockFilterChain(Filter... filters) {
Assert.notNull(filters, "filters cannot be null");
Assert.notEmpty(filters, "filters cannot be empty");
Assert.noNullElements(filters, "filters cannot contain null values");
this.iterator = Arrays.asList(filters).iterator();
}
/**
* Invoke registered {@link Filter}s and/or {@link Servlet} also saving the
* request and response.
*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
throw new IllegalStateException("This FilterChain has already been called!");
}
if ((this.iterator != null) && (this.iterator.hasNext())) {
Filter nextFilter = this.iterator.next();
nextFilter.doFilter(request, response, this);
}
this.request = request;
this.response = response;
}
@ -67,4 +131,35 @@ public class MockFilterChain implements FilterChain {
return this.response;
}
/**
* A filter that simply delegates to a Servlet.
*/
private static class ServletFilterProxy implements Filter {
private final Servlet delegateServlet;
private ServletFilterProxy(Servlet servlet) {
Assert.notNull(servlet, "servlet cannot be null");
this.delegateServlet = servlet;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
this.delegateServlet.service(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
}
@Override
public String toString() {
return this.delegateServlet.toString();
}
}
}