extended Servlet API mocks for Servlet 3.0 forward compatibility as far as possible; made MockHttpServletResponse compatible with Servlet 3.0 getHeader(s) method returning Strings (SPR-8529); added getHeaderValue(s) method to MockHttpServletResponse for raw value access

This commit is contained in:
Juergen Hoeller 2011-07-15 14:16:31 +00:00
parent 4e1cb2b823
commit 18ab057e90
5 changed files with 166 additions and 61 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2011 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.
@ -71,6 +71,10 @@ class HeaderValueHolder {
return (!this.values.isEmpty() ? this.values.get(0) : null);
}
public String getStringValue() {
return (!this.values.isEmpty() ? this.values.get(0).toString() : null);
}
/**
* Find a HeaderValueHolder by name, ignoring casing.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -18,6 +18,7 @@ package org.springframework.mock.web;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
@ -35,24 +36,24 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
/**
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
* interface. Supports the Servlet 2.5 API level.
* <p>
* Used for testing the web framework; also useful for testing application
* controllers.
*
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest} interface.
*
* <p>Compatible with Servlet 2.5 and partially with Servlet 3.0 (notable exceptions:
* the <code>getPart(s)</code> and <code>startAsync</code> families of methods).
*
* @author Juergen Hoeller
* @author Rod Johnson
* @author Rick Evans
@ -93,6 +94,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
private boolean active = true;
// ---------------------------------------------------------------------
// ServletRequest properties
// ---------------------------------------------------------------------
@ -134,6 +136,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
private int localPort = DEFAULT_SERVER_PORT;
// ---------------------------------------------------------------------
// HttpServletRequest properties
// ---------------------------------------------------------------------
@ -180,7 +183,6 @@ public class MockHttpServletRequest implements HttpServletRequest {
/**
* Create a new MockHttpServletRequest with a default
* {@link MockServletContext}.
*
* @see MockServletContext
*/
public MockHttpServletRequest() {
@ -190,7 +192,6 @@ public class MockHttpServletRequest implements HttpServletRequest {
/**
* Create a new MockHttpServletRequest with a default
* {@link MockServletContext}.
*
* @param method the request method (may be <code>null</code>)
* @param requestURI the request URI (may be <code>null</code>)
* @see #setMethod
@ -203,7 +204,6 @@ public class MockHttpServletRequest implements HttpServletRequest {
/**
* Create a new MockHttpServletRequest.
*
* @param servletContext the ServletContext that the request runs in (may be
* <code>null</code> to use a default MockServletContext)
* @see MockServletContext
@ -214,7 +214,6 @@ public class MockHttpServletRequest implements HttpServletRequest {
/**
* Create a new MockHttpServletRequest.
*
* @param servletContext the ServletContext that the request runs in (may be
* <code>null</code> to use a default MockServletContext)
* @param method the request method (may be <code>null</code>)
@ -230,6 +229,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
this.locales.add(Locale.ENGLISH);
}
// ---------------------------------------------------------------------
// Lifecycle methods
// ---------------------------------------------------------------------
@ -274,6 +274,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
}
// ---------------------------------------------------------------------
// ServletRequest interface
// ---------------------------------------------------------------------
@ -603,6 +604,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
return this.localPort;
}
// ---------------------------------------------------------------------
// HttpServletRequest interface
// ---------------------------------------------------------------------
@ -625,18 +627,15 @@ public class MockHttpServletRequest implements HttpServletRequest {
/**
* Add a header entry for the given name.
* <p>
* If there was no entry for that header name before, the value will be used
* <p>If there was no entry for that header name before, the value will be used
* as-is. In case of an existing entry, a String array will be created,
* adding the given value (more specifically, its toString representation)
* as further element.
* <p>
* Multiple values can only be stored as list of Strings, following the
* <p>Multiple values can only be stored as list of Strings, following the
* Servlet spec (see <code>getHeaders</code> accessor). As alternative to
* repeated <code>addHeader</code> calls for individual elements, you can
* use a single call with an entire array or Collection of values as
* parameter.
*
* @see #getHeaderNames
* @see #getHeader
* @see #getHeaders
@ -680,20 +679,6 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
}
public String getHeader(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getValue().toString() : null);
}
public Enumeration<String> getHeaders(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return Collections.enumeration(header != null ? header.getStringValues() : new LinkedList<String>());
}
public Enumeration<String> getHeaderNames() {
return Collections.enumeration(this.headers.keySet());
}
public int getIntHeader(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
Object value = (header != null ? header.getValue() : null);
@ -711,6 +696,20 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
}
public String getHeader(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getStringValue() : null);
}
public Enumeration<String> getHeaders(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return Collections.enumeration(header != null ? header.getStringValues() : new LinkedList<String>());
}
public Enumeration<String> getHeaderNames() {
return Collections.enumeration(this.headers.keySet());
}
public void setMethod(String method) {
this.method = method;
}
@ -760,7 +759,8 @@ public class MockHttpServletRequest implements HttpServletRequest {
}
public boolean isUserInRole(String role) {
return this.userRoles.contains(role);
return (this.userRoles.contains(role) || (this.servletContext instanceof MockServletContext &&
((MockServletContext) this.servletContext).getDeclaredRoles().contains(role)));
}
public void setUserPrincipal(Principal userPrincipal) {
@ -855,4 +855,18 @@ public class MockHttpServletRequest implements HttpServletRequest {
return isRequestedSessionIdFromURL();
}
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
return (this.userPrincipal != null && this.remoteUser != null && this.authType != null);
}
public void login(String username, String password) throws ServletException {
throw new ServletException("Username-password authentication not supported - override the login method");
}
public void logout() throws ServletException {
this.userPrincipal = null;
this.remoteUser = null;
this.authType = null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -38,11 +38,9 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.util.WebUtils;
/**
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse}
* interface. Supports the Servlet 2.5 API level.
* Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface.
*
* <p>Used for testing the web framework; also useful for testing
* application controllers.
* <p>Compatible with Servlet 2.5 as well as Servlet 3.0.
*
* @author Juergen Hoeller
* @author Rod Johnson
@ -50,8 +48,6 @@ import org.springframework.web.util.WebUtils;
*/
public class MockHttpServletResponse implements HttpServletResponse {
public static final int DEFAULT_SERVER_PORT = 80;
private static final String CHARSET_PREFIX = "charset=";
@ -280,19 +276,52 @@ public class MockHttpServletResponse implements HttpServletResponse {
/**
* Return the names of all specified headers as a Set of Strings.
* <p>As of Servlet 3.0, this method is also defined HttpServletResponse.
* @return the <code>Set</code> of header name <code>Strings</code>, or an empty <code>Set</code> if none
*/
public Set<String> getHeaderNames() {
return this.headers.keySet();
}
/**
* Return the primary value for the given header as a String, if any.
* Will return the first value in case of multiple values.
* <p>As of Servlet 3.0, this method is also defined HttpServletResponse.
* As of Spring 3.1, it returns a stringified value for Servlet 3.0 compatibility.
* Consider using {@link #getHeaderValue(String)} for raw Object access.
* @param name the name of the header
* @return the associated header value, or <code>null<code> if none
*/
public String getHeader(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getStringValue() : null);
}
/**
* Return all values for the given header as a List of Strings.
* <p>As of Servlet 3.0, this method is also defined HttpServletResponse.
* As of Spring 3.1, it returns a List of stringified values for Servlet 3.0 compatibility.
* Consider using {@link #getHeaderValues(String)} for raw Object access.
* @param name the name of the header
* @return the associated header values, or an empty List if none
*/
public List<String> getHeaders(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
if (header != null) {
return header.getStringValues();
}
else {
return Collections.emptyList();
}
}
/**
* Return the primary value for the given header, if any.
* <p>Will return the first value in case of multiple values.
* @param name the name of the header
* @return the associated header value, or <code>null<code> if none
*/
public Object getHeader(String name) {
public Object getHeaderValue(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getValue() : null);
}
@ -302,9 +331,14 @@ public class MockHttpServletResponse implements HttpServletResponse {
* @param name the name of the header
* @return the associated header values, or an empty List if none
*/
public List<Object> getHeaders(String name) {
public List<Object> getHeaderValues(String name) {
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name);
return (header != null ? header.getValues() : Collections.emptyList());
if (header != null) {
return header.getValues();
}
else {
return Collections.emptyList();
}
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -23,7 +23,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Vector;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
@ -34,11 +33,9 @@ import org.springframework.util.Assert;
/**
* Mock implementation of the {@link javax.servlet.http.HttpSession} interface.
* Supports the Servlet 2.4 API level.
* <p>
* Used for testing the web framework; also useful for testing application
* controllers.
*
*
* <p>Compatible with Servlet 2.5 as well as Servlet 3.0.
*
* @author Juergen Hoeller
* @author Rod Johnson
* @author Mark Fisher
@ -47,8 +44,6 @@ import org.springframework.util.Assert;
@SuppressWarnings("deprecation")
public class MockHttpSession implements HttpSession {
public static final String SESSION_COOKIE_NAME = "JSESSION";
private static int nextId = 1;
private final String id;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2011 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.
@ -42,12 +42,20 @@ import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.util.WebUtils;
/**
* Mock implementation of the {@link javax.servlet.ServletContext} interface.
*
* <p>Compatible with Servlet 2.5 and partially with Servlet 3.0. Can be configured to
* expose a specific version through {@link #setMajorVersion}/{@link #setMinorVersion};
* default is 2.5. Note that Servlet 3.0 support is limited: servlet, filter and listener
* registration methods are not supported; neither is cookie or JSP configuration.
* We generally do not recommend to unit-test your ServletContainerInitializers and
* WebApplicationInitializers which is where those registration methods would be used.
*
* <p>Used for testing the Spring web framework; only rarely necessary for testing
* application controllers. As long as application components don't explicitly
* access the ServletContext, ClassPathXmlApplicationContext or
@ -90,8 +98,14 @@ public class MockServletContext implements ServletContext {
private String contextPath = "";
private int majorVersion = 2;
private int minorVersion = 5;
private int effectiveMajorVersion = 2;
private int effectiveMinorVersion = 5;
private final Map<String, ServletContext> contexts = new HashMap<String, ServletContext>();
private final Map<String, String> initParameters = new LinkedHashMap<String, String>();
@ -100,6 +114,8 @@ public class MockServletContext implements ServletContext {
private String servletContextName = "MockServletContext";
private final Set<String> declaredRoles = new HashSet<String>();
/**
* Create a new MockServletContext, using no base path and a
@ -179,14 +195,15 @@ public class MockServletContext implements ServletContext {
return this.contexts.get(contextPath);
}
public void setMajorVersion(int majorVersion) {
this.majorVersion = majorVersion;
}
public int getMajorVersion() {
return 2;
return this.majorVersion;
}
public void setMinorVersion(int minorVersion) {
if (minorVersion < 3 || minorVersion > 5) {
throw new IllegalArgumentException("Only Servlet minor versions between 3 and 5 are supported");
}
this.minorVersion = minorVersion;
}
@ -194,6 +211,22 @@ public class MockServletContext implements ServletContext {
return this.minorVersion;
}
public void setEffectiveMajorVersion(int effectiveMajorVersion) {
this.effectiveMajorVersion = effectiveMajorVersion;
}
public int getEffectiveMajorVersion() {
return this.effectiveMajorVersion;
}
public void setEffectiveMinorVersion(int effectiveMinorVersion) {
this.effectiveMinorVersion = effectiveMinorVersion;
}
public int getEffectiveMinorVersion() {
return this.effectiveMinorVersion;
}
public String getMimeType(String filePath) {
return MimeTypeResolver.getMimeType(filePath);
}
@ -309,15 +342,24 @@ public class MockServletContext implements ServletContext {
return this.initParameters.get(name);
}
public Enumeration<String> getInitParameterNames() {
return Collections.enumeration(this.initParameters.keySet());
}
public boolean setInitParameter(String name, String value) {
Assert.notNull(name, "Parameter name must not be null");
if (this.initParameters.containsKey(name)) {
return false;
}
this.initParameters.put(name, value);
return true;
}
public void addInitParameter(String name, String value) {
Assert.notNull(name, "Parameter name must not be null");
this.initParameters.put(name, value);
}
public Enumeration<String> getInitParameterNames() {
return Collections.enumeration(this.initParameters.keySet());
}
public Object getAttribute(String name) {
Assert.notNull(name, "Attribute name must not be null");
return this.attributes.get(name);
@ -350,6 +392,22 @@ public class MockServletContext implements ServletContext {
return this.servletContextName;
}
public ClassLoader getClassLoader() {
return ClassUtils.getDefaultClassLoader();
}
public void declareRoles(String... roleNames) {
Assert.notNull(roleNames, "Role names array must not be null");
for (String roleName : roleNames) {
Assert.hasLength(roleName, "Role name must not be empty");
this.declaredRoles.add(roleName);
}
}
public Set<String> getDeclaredRoles() {
return Collections.unmodifiableSet(this.declaredRoles);
}
/**
* Inner factory class used to just introduce a Java Activation Framework