/* * Copyright 2002-2017 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.test.web.servlet.request; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import org.junit.Before; import org.junit.Test; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpSession; import org.springframework.mock.web.MockServletContext; import org.springframework.util.FileCopyUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.servlet.FlashMap; import org.springframework.web.servlet.support.SessionFlashMapManager; import org.springframework.web.util.UriComponentsBuilder; import static org.junit.Assert.*; /** * Unit tests for building a {@link MockHttpServletRequest} with * {@link MockHttpServletRequestBuilder}. * * @author Rossen Stoyanchev * @author Sam Brannen */ public class MockHttpServletRequestBuilderTests { private final ServletContext servletContext = new MockServletContext(); private MockHttpServletRequestBuilder builder; @Before public void setUp() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo/bar"); } @Test public void method() { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("GET", request.getMethod()); } @Test public void uri() { String uri = "https://java.sun.com:8080/javase/6/docs/api/java/util/BitSet.html?foo=bar#and(java.util.BitSet)"; this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, uri); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("https", request.getScheme()); assertEquals("foo=bar", request.getQueryString()); assertEquals("java.sun.com", request.getServerName()); assertEquals(8080, request.getServerPort()); assertEquals("/javase/6/docs/api/java/util/BitSet.html", request.getRequestURI()); assertEquals("https://java.sun.com:8080/javase/6/docs/api/java/util/BitSet.html", request.getRequestURL().toString()); } @Test public void requestUriWithEncoding() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/foo%20bar", request.getRequestURI()); } @Test // SPR-13435 public void requestUriWithDoubleSlashes() throws URISyntaxException { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, new URI("/test//currentlyValid/0")); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/test//currentlyValid/0", request.getRequestURI()); } @Test public void contextPathEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("", request.getContextPath()); assertEquals("", request.getServletPath()); assertEquals("/foo", request.getPathInfo()); } @Test public void contextPathServletPathEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/hotels/42"); this.builder.contextPath("/travel"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/travel", request.getContextPath()); assertEquals("", request.getServletPath()); assertEquals("/hotels/42", request.getPathInfo()); } @Test public void contextPathServletPath() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/main/hotels/42"); this.builder.contextPath("/travel"); this.builder.servletPath("/main"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/travel", request.getContextPath()); assertEquals("/main", request.getServletPath()); assertEquals("/hotels/42", request.getPathInfo()); } @Test public void contextPathServletPathInfoEmpty() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/travel/hotels/42"); this.builder.contextPath("/travel"); this.builder.servletPath("/hotels/42"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/travel", request.getContextPath()); assertEquals("/hotels/42", request.getServletPath()); assertNull(request.getPathInfo()); } @Test public void contextPathServletPathInfo() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); this.builder.servletPath("/index.html"); this.builder.pathInfo(null); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("", request.getContextPath()); assertEquals("/index.html", request.getServletPath()); assertNull(request.getPathInfo()); } @Test public void contextPathServletPathInvalid() { testContextPathServletPathInvalid("/Foo", "", "Request URI [/foo/bar] does not start with context path [/Foo]"); testContextPathServletPathInvalid("foo", "", "Context path must start with a '/'"); testContextPathServletPathInvalid("/foo/", "", "Context path must not end with a '/'"); testContextPathServletPathInvalid("/foo", "/Bar", "Invalid servlet path [/Bar] for request URI [/foo/bar]"); testContextPathServletPathInvalid("/foo", "bar", "Servlet path must start with a '/'"); testContextPathServletPathInvalid("/foo", "/bar/", "Servlet path must not end with a '/'"); } private void testContextPathServletPathInvalid(String contextPath, String servletPath, String message) { try { this.builder.contextPath(contextPath); this.builder.servletPath(servletPath); this.builder.buildRequest(this.servletContext); } catch (IllegalArgumentException ex) { assertEquals(message, ex.getMessage()); } } @Test public void requestUriAndFragment() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo#bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("/foo", request.getRequestURI()); } @Test public void requestParameter() { this.builder.param("foo", "bar", "baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map<String, String[]> parameterMap = request.getParameterMap(); assertArrayEquals(new String[] {"bar", "baz"}, parameterMap.get("foo")); } @Test public void requestParameterFromQuery() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo=bar&foo=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map<String, String[]> parameterMap = request.getParameterMap(); assertArrayEquals(new String[] {"bar", "baz"}, parameterMap.get("foo")); assertEquals("foo=bar&foo=baz", request.getQueryString()); } @Test public void requestParameterFromQueryList() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo[0]=bar&foo[1]=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("foo%5B0%5D=bar&foo%5B1%5D=baz", request.getQueryString()); assertEquals("bar", request.getParameter("foo[0]")); assertEquals("baz", request.getParameter("foo[1]")); } @Test public void requestParameterFromQueryWithEncoding() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo={value}", "bar=baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("foo=bar%3Dbaz", request.getQueryString()); assertEquals("bar=baz", request.getParameter("foo")); } @Test // SPR-11043 public void requestParameterFromQueryNull() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Map<String, String[]> parameterMap = request.getParameterMap(); assertArrayEquals(new String[] {null}, parameterMap.get("foo")); assertEquals("foo", request.getQueryString()); } @Test // SPR-13801 public void requestParameterFromMultiValueMap() throws Exception { MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("foo", "bar"); params.add("foo", "baz"); this.builder = new MockHttpServletRequestBuilder(HttpMethod.POST, "/foo"); this.builder.params(params); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertArrayEquals(new String[] {"bar", "baz"}, request.getParameterMap().get("foo")); } @Test public void requestParameterFromRequestBodyFormData() throws Exception { String contentType = "application/x-www-form-urlencoded;charset=UTF-8"; String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3"; MockHttpServletRequest request = new MockHttpServletRequestBuilder(HttpMethod.POST, "/foo") .contentType(contentType).content(body.getBytes(StandardCharsets.UTF_8)) .buildRequest(this.servletContext); assertArrayEquals(new String[] {"value 1"}, request.getParameterMap().get("name 1")); assertArrayEquals(new String[] {"value A", "value B"}, request.getParameterMap().get("name 2")); assertArrayEquals(new String[] {null}, request.getParameterMap().get("name 3")); } @Test public void acceptHeader() { this.builder.accept(MediaType.TEXT_HTML, MediaType.APPLICATION_XML); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); List<String> accept = Collections.list(request.getHeaders("Accept")); List<MediaType> result = MediaType.parseMediaTypes(accept.get(0)); assertEquals(1, accept.size()); assertEquals("text/html", result.get(0).toString()); assertEquals("application/xml", result.get(1).toString()); } @Test public void contentType() { this.builder.contentType(MediaType.TEXT_HTML); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); String contentType = request.getContentType(); List<String> contentTypes = Collections.list(request.getHeaders("Content-Type")); assertEquals("text/html", contentType); assertEquals(1, contentTypes.size()); assertEquals("text/html", contentTypes.get(0)); } @Test public void contentTypeViaString() { this.builder.contentType("text/html"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); String contentType = request.getContentType(); List<String> contentTypes = Collections.list(request.getHeaders("Content-Type")); assertEquals("text/html", contentType); assertEquals(1, contentTypes.size()); assertEquals("text/html", contentTypes.get(0)); } @Test // SPR-11308 public void contentTypeViaHeader() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); String contentType = request.getContentType(); assertEquals("text/html", contentType); } @Test // SPR-11308 public void contentTypeViaMultipleHeaderValues() { this.builder.header("Content-Type", MediaType.TEXT_HTML_VALUE, MediaType.ALL_VALUE); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("text/html", request.getContentType()); } @Test public void body() throws IOException { byte[] body = "Hello World".getBytes("UTF-8"); this.builder.content(body); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); byte[] result = FileCopyUtils.copyToByteArray(request.getInputStream()); assertArrayEquals(body, result); } @Test public void header() { this.builder.header("foo", "bar", "baz"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); List<String> headers = Collections.list(request.getHeaders("foo")); assertEquals(2, headers.size()); assertEquals("bar", headers.get(0)); assertEquals("baz", headers.get(1)); } @Test public void headers() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.put("foo", Arrays.asList("bar", "baz")); this.builder.headers(httpHeaders); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); List<String> headers = Collections.list(request.getHeaders("foo")); assertEquals(2, headers.size()); assertEquals("bar", headers.get(0)); assertEquals("baz", headers.get(1)); assertEquals(MediaType.APPLICATION_JSON.toString(), request.getHeader("Content-Type")); } @Test public void cookie() { Cookie cookie1 = new Cookie("foo", "bar"); Cookie cookie2 = new Cookie("baz", "qux"); this.builder.cookie(cookie1, cookie2); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); Cookie[] cookies = request.getCookies(); assertEquals(2, cookies.length); assertEquals("foo", cookies[0].getName()); assertEquals("bar", cookies[0].getValue()); assertEquals("baz", cookies[1].getName()); assertEquals("qux", cookies[1].getValue()); } @Test public void noCookies() { MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertNull(request.getCookies()); } @Test public void locale() { Locale locale = new Locale("nl", "nl"); this.builder.locale(locale); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals(locale, request.getLocale()); } @Test public void characterEncoding() { String encoding = "UTF-8"; this.builder.characterEncoding(encoding); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals(encoding, request.getCharacterEncoding()); } @Test public void requestAttribute() { this.builder.requestAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("bar", request.getAttribute("foo")); } @Test public void sessionAttribute() { this.builder.sessionAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("bar", request.getSession().getAttribute("foo")); } @Test public void sessionAttributes() { Map<String, Object> map = new HashMap<>(); map.put("foo", "bar"); this.builder.sessionAttrs(map); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals("bar", request.getSession().getAttribute("foo")); } @Test public void session() { MockHttpSession session = new MockHttpSession(this.servletContext); session.setAttribute("foo", "bar"); this.builder.session(session); this.builder.sessionAttr("baz", "qux"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals(session, request.getSession()); assertEquals("bar", request.getSession().getAttribute("foo")); assertEquals("qux", request.getSession().getAttribute("baz")); } @Test public void flashAttribute() { this.builder.flashAttr("foo", "bar"); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); FlashMap flashMap = new SessionFlashMapManager().retrieveAndUpdate(request, null); assertNotNull(flashMap); assertEquals("bar", flashMap.get("foo")); } @Test public void principal() { User user = new User(); this.builder.principal(user); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals(user, request.getUserPrincipal()); } @Test // SPR-12945 public void mergeInvokesDefaultRequestPostProcessorFirst() { final String ATTR = "ATTR"; final String EXPECTED = "override"; MockHttpServletRequestBuilder defaultBuilder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/foo/bar") .with(requestAttr(ATTR).value("default")) .with(requestAttr(ATTR).value(EXPECTED)); builder.merge(defaultBuilder); MockHttpServletRequest request = builder.buildRequest(servletContext); request = builder.postProcessRequest(request); assertEquals(EXPECTED, request.getAttribute(ATTR)); } @Test // SPR-13719 public void arbitraryMethod() { String httpMethod = "REPort"; URI url = UriComponentsBuilder.fromPath("/foo/{bar}").buildAndExpand(42).toUri(); this.builder = new MockHttpServletRequestBuilder(httpMethod, url); MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); assertEquals(httpMethod, request.getMethod()); assertEquals("/foo/42", request.getPathInfo()); } private static RequestAttributePostProcessor requestAttr(String attrName) { return new RequestAttributePostProcessor().attr(attrName); } private final class User implements Principal { @Override public String getName() { return "Foo"; } } private static class RequestAttributePostProcessor implements RequestPostProcessor { String attr; String value; public RequestAttributePostProcessor attr(String attr) { this.attr = attr; return this; } public RequestAttributePostProcessor value(String value) { this.value = value; return this; } public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { request.setAttribute(attr, value); return request; } } }