Browse Source

Add URI based MockHttpServletRequestBuilder constructors

This commit adds new MockHttpServletRequestBuilder constructors
with an URI parameter in addition to the URL template + URL variables
existing ones.

It gives more control on how the URL is built, allowing for example to
use URL variables containing '/' character with proper encoding.

Issue: SPR-11441
pull/496/head
Sebastien Deleuze 11 years ago committed by Rossen Stoyanchev
parent
commit
0b69a0ba4b
  1. 19
      spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java
  2. 15
      spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java
  3. 79
      spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java
  4. 131
      spring-test/src/test/java/org/springframework/test/web/servlet/Spr11441Tests.java

19
spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
package org.springframework.test.web.servlet.request;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
@ -114,6 +115,7 @@ public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable @@ -114,6 +115,7 @@ public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable
* <p>Although this class cannot be extended, additional ways to initialize
* the {@code MockHttpServletRequest} can be plugged in via
* {@link #with(RequestPostProcessor)}.
* @param httpMethod the HTTP method (GET, POST, etc)
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param urlVariables zero or more URL variables
*/
@ -124,6 +126,23 @@ public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable @@ -124,6 +126,23 @@ public class MockHttpServletRequestBuilder implements RequestBuilder, Mergeable
this.uriComponents = UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(urlVariables).encode();
}
/**
* Package private constructor. To get an instance, use static factory
* methods in {@link MockMvcRequestBuilders}.
* <p>Although this class cannot be extended, additional ways to initialize
* the {@code MockHttpServletRequest} can be plugged in via
* {@link #with(RequestPostProcessor)}.
* @param httpMethod the HTTP method (GET, POST, etc)
* @param url the URL
* @since 4.0.3
*/
MockHttpServletRequestBuilder(HttpMethod httpMethod, URI url) {
Assert.notNull(httpMethod, "httpMethod is required");
Assert.notNull(url, "url is required");
this.method = httpMethod;
this.uriComponents = UriComponentsBuilder.fromUri(url).build();
}
/**
* Add a request parameter to the {@link MockHttpServletRequest}.
* If called more than once, the new values are added.

15
spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.test.web.servlet.request;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
@ -52,6 +53,20 @@ public class MockMultipartHttpServletRequestBuilder extends MockHttpServletReque @@ -52,6 +53,20 @@ public class MockMultipartHttpServletRequestBuilder extends MockHttpServletReque
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
/**
* Package-private constructor. Use static factory methods in
* {@link MockMvcRequestBuilders}.
* <p>For other ways to initialize a {@code MockMultipartHttpServletRequest},
* see {@link #with(RequestPostProcessor)} and the
* {@link RequestPostProcessor} extension point.
* @param url the URL
* @since 4.0.3
*/
MockMultipartHttpServletRequestBuilder(URI url) {
super(HttpMethod.POST, url);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
/**
* Create a new MockMultipartFile with the given content.

79
spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@ -22,6 +22,8 @@ import org.springframework.mock.web.MockHttpServletRequest; @@ -22,6 +22,8 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import java.net.URI;
/**
* Static factory methods for {@link RequestBuilder}s.
*
@ -31,6 +33,7 @@ import org.springframework.test.web.servlet.RequestBuilder; @@ -31,6 +33,7 @@ import org.springframework.test.web.servlet.RequestBuilder;
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Greg Turnquist
* @author Sebastien Deleuze
* @since 3.2
*/
public abstract class MockMvcRequestBuilders {
@ -109,6 +112,80 @@ public abstract class MockMvcRequestBuilders { @@ -109,6 +112,80 @@ public abstract class MockMvcRequestBuilders {
return new MockMultipartHttpServletRequestBuilder(urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a GET request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder get(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.GET, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a POST request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder post(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.POST, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a PUT request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder put(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.PUT, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a PATCH request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder patch(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.PATCH, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a DELETE request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder delete(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.DELETE, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for an OPTIONS request.
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder options(URI url) {
return new MockHttpServletRequestBuilder(HttpMethod.OPTIONS, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP method.
* @param httpMethod the HTTP method (GET, POST, etc)
* @param url the URL
* @since 4.0.3
*/
public static MockHttpServletRequestBuilder request(HttpMethod httpMethod, URI url) {
return new MockHttpServletRequestBuilder(httpMethod, url);
}
/**
* Create a {@link MockHttpServletRequestBuilder} for a multipart request.
* @param url the URL
* @since 4.0.3
*/
public static MockMultipartHttpServletRequestBuilder fileUpload(URI url) {
return new MockMultipartHttpServletRequestBuilder(url);
}
/**
* Create a {@link RequestBuilder} for an async dispatch from the
* {@link MvcResult} of the request that started async processing.

131
spring-test/src/test/java/org/springframework/test/web/servlet/Spr11441Tests.java

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
/*
* Copyright 2002-2014 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;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import static org.hamcrest.core.Is.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
/**
* Tests for SPR-11441 (MockMvc needs to accept prepared URI with encoded URI path variables).
*
* @author Sebastien Deleuze
*/
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration
public class Spr11441Tests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
}
@Test
public void test() throws Exception {
String id = "a/b";
URI url = UriComponentsBuilder.fromUriString("/circuit").pathSegment(id).build().encode().toUri();
ResultActions result = mockMvc.perform(get(url));
result.andExpect(status().isOk()).andExpect(model().attribute("receivedId", is(id)));
}
@Configuration
@EnableWebMvc
static class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public MyController myController() {
return new MyController();
}
@Bean
public HandlerMappingConfigurer myHandlerMappingConfigurer() {
return new HandlerMappingConfigurer();
}
}
@Controller
private static class MyController {
@RequestMapping(value = "/circuit/{id}", method = RequestMethod.GET)
public String getCircuit(@PathVariable String id, Model model) {
model.addAttribute("receivedId", id);
return "result";
}
}
@Component
private static class HandlerMappingConfigurer implements BeanPostProcessor, PriorityOrdered {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerMapping) {
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) bean;
// URL decode after request mapping, not before.
requestMappingHandlerMapping.setUrlDecode(false);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public int getOrder() {
return PriorityOrdered.HIGHEST_PRECEDENCE;
}
}
}
Loading…
Cancel
Save