diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java index 75a50db9df73..c39e3dbee0be 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/MockMvcBuilderSupport.java @@ -43,11 +43,12 @@ public abstract class MockMvcBuilderSupport { protected final MockMvc createMockMvc(Filter[] filters, MockServletConfig servletConfig, WebApplicationContext webAppContext, RequestBuilder defaultRequestBuilder, - List globalResultMatchers, List globalResultHandlers) { + List globalResultMatchers, List globalResultHandlers, Boolean dispatchOptions) { ServletContext servletContext = webAppContext.getServletContext(); TestDispatcherServlet dispatcherServlet = new TestDispatcherServlet(webAppContext); + dispatcherServlet.setDispatchOptionsRequest(dispatchOptions); try { dispatcherServlet.init(servletConfig); } diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java index da96fd9cd225..f93b8fb7c034 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java @@ -79,6 +79,17 @@ public static MockHttpServletRequestBuilder put(String urlTemplate, Object... ur public static MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) { return new MockHttpServletRequestBuilder(HttpMethod.DELETE, urlTemplate, urlVariables); } + + /** + * Create a {@link MockHttpServletRequestBuilder} for a OPTIONS request. + * + * @param urlTemplate a URL template; the resulting URL will be encoded + * @param urlVariables zero or more URL variables + */ + public static MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables) { + return new MockHttpServletRequestBuilder(HttpMethod.OPTIONS, urlTemplate, urlVariables); + } + /** * Create a {@link MockHttpServletRequestBuilder} for a request with the given HTTP method. diff --git a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/setup/DefaultMockMvcBuilder.java b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/setup/DefaultMockMvcBuilder.java index a97b38aeee22..984be0c8542f 100644 --- a/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/setup/DefaultMockMvcBuilder.java +++ b/spring-test-mvc/src/main/java/org/springframework/test/web/servlet/setup/DefaultMockMvcBuilder.java @@ -31,6 +31,7 @@ import org.springframework.test.web.servlet.ResultMatcher; import org.springframework.util.Assert; import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; /** * An concrete implementation of {@link MockMvcBuilder} with methods for @@ -53,6 +54,8 @@ public class DefaultMockMvcBuilder extends MockMvcB private final List globalResultMatchers = new ArrayList(); private final List globalResultHandlers = new ArrayList(); + + private Boolean dispatchOptions = Boolean.FALSE; /** @@ -177,6 +180,17 @@ public final T alwaysDo(ResultHandler resultHandler) { this.globalResultHandlers.add(resultHandler); return (T) this; } + + /** + * Should the {@link DispatcherServlet} dispatch OPTIONS request to controllers. + * @param dispatchOptions + * @see {@link DispatcherServlet#setDispatchOptionsRequest(boolean)} + */ + @SuppressWarnings("unchecked") + public final T dispatchOptions(boolean dispatchOptions) { + this.dispatchOptions = dispatchOptions; + return (T) this; + } /** * Build a {@link MockMvc} instance. @@ -191,7 +205,7 @@ public final MockMvc build() { Filter[] filterArray = this.filters.toArray(new Filter[this.filters.size()]); return super.createMockMvc(filterArray, mockServletConfig, this.webAppContext, - this.defaultRequestBuilder, this.globalResultMatchers, this.globalResultHandlers); + this.defaultRequestBuilder, this.globalResultMatchers, this.globalResultHandlers,this.dispatchOptions); } /** diff --git a/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/Spr10093Tests.java b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/Spr10093Tests.java new file mode 100644 index 000000000000..0ffc0039eaa8 --- /dev/null +++ b/spring-test-mvc/src/test/java/org/springframework/test/web/servlet/Spr10093Tests.java @@ -0,0 +1,81 @@ +/** + * + */ +package org.springframework.test.web.servlet; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +/** + * Tests for SPR-10093 (support for OPTIONS requests). + * @author Arnaud Cogoluègnes + */ +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration +public class Spr10093Tests { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = webAppContextSetup(this.wac).dispatchOptions(true).build(); + } + + @Test + public void test() throws Exception { + MyController controller = wac.getBean(MyController.class); + int initialCount = controller.counter.get(); + this.mockMvc.perform(options("/myUrl")).andExpect(status().isOk()); + Assert.assertEquals(initialCount+1,controller.counter.get()); + } + + + @Configuration + @EnableWebMvc + static class WebConfig extends WebMvcConfigurerAdapter { + + @Bean + public MyController myController() { + return new MyController(); + } + } + + @Controller + private static class MyController { + + private AtomicInteger counter = new AtomicInteger(0); + + @RequestMapping(value="/myUrl",method=RequestMethod.OPTIONS) + @ResponseBody + public void handle() { + counter.incrementAndGet(); + } + } + + +}