Support placeholder values in Spring MVC Test
Issue: SPR-10825
This commit is contained in:
@@ -19,9 +19,12 @@ package org.springframework.test.web.servlet.setup;
|
||||
import java.util.ArrayList;
|
||||
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 org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
@@ -30,6 +33,9 @@ import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.accept.ContentNegotiationManager;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
@@ -110,6 +116,8 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
|
||||
private Boolean removeSemicolonContent;
|
||||
|
||||
private Map<String, String> placeHolderValues = new HashMap<String, String>();
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor. Not intended for direct instantiation.
|
||||
@@ -282,10 +290,23 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
* if provided, is in turn set on
|
||||
* {@link AbstractHandlerMapping#setRemoveSemicolonContent(boolean)}.
|
||||
*/
|
||||
public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
|
||||
public StandaloneMockMvcBuilder setRemoveSemicolonContent(boolean removeSemicolonContent) {
|
||||
this.removeSemicolonContent = removeSemicolonContent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* In a standalone setup there is no support for placeholder values embedded in
|
||||
* request mappings. This method allows manually provided placeholder values so they
|
||||
* can be resolved. Alternatively consider creating a test that initializes a
|
||||
* {@link WebApplicationContext}.
|
||||
*/
|
||||
public StandaloneMockMvcBuilder addPlaceHolderValues(String name, String value) {
|
||||
this.placeHolderValues.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initWebAppContext(WebApplicationContext cxt) {
|
||||
StubWebApplicationContext mockCxt = (StubWebApplicationContext) cxt;
|
||||
@@ -295,20 +316,19 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
|
||||
private void registerMvcSingletons(StubWebApplicationContext cxt) {
|
||||
|
||||
StandaloneConfiguration configuration = new StandaloneConfiguration();
|
||||
StandaloneConfiguration config = new StandaloneConfiguration();
|
||||
|
||||
RequestMappingHandlerMapping handlerMapping = configuration.requestMappingHandlerMapping();
|
||||
handlerMapping.setServletContext(cxt.getServletContext());
|
||||
handlerMapping.setApplicationContext(cxt);
|
||||
cxt.addBean("requestMappingHandlerMapping", handlerMapping);
|
||||
StaticRequestMappingHandlerMapping hm = config.getHandlerMapping(cxt);
|
||||
hm.registerHandlers(controllers);
|
||||
cxt.addBean("requestMappingHandlerMapping", hm);
|
||||
|
||||
RequestMappingHandlerAdapter handlerAdapter = configuration.requestMappingHandlerAdapter();
|
||||
RequestMappingHandlerAdapter handlerAdapter = config.requestMappingHandlerAdapter();
|
||||
handlerAdapter.setServletContext(cxt.getServletContext());
|
||||
handlerAdapter.setApplicationContext(cxt);
|
||||
handlerAdapter.afterPropertiesSet();
|
||||
cxt.addBean("requestMappingHandlerAdapter", handlerAdapter);
|
||||
|
||||
cxt.addBean("handlerExceptionResolver", configuration.handlerExceptionResolver());
|
||||
cxt.addBean("handlerExceptionResolver", config.handlerExceptionResolver());
|
||||
|
||||
cxt.addBeans(initViewResolvers(cxt));
|
||||
cxt.addBean(DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME, this.localeResolver);
|
||||
@@ -337,12 +357,13 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
/** Using the MVC Java configuration as the starting point for the "standalone" setup */
|
||||
private class StandaloneConfiguration extends WebMvcConfigurationSupport {
|
||||
|
||||
@Override
|
||||
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
|
||||
|
||||
public StaticRequestMappingHandlerMapping getHandlerMapping(StubWebApplicationContext cxt) {
|
||||
|
||||
StaticRequestMappingHandlerMapping handlerMapping = new StaticRequestMappingHandlerMapping();
|
||||
handlerMapping.registerHandlers(controllers);
|
||||
|
||||
handlerMapping.setServletContext(cxt.getServletContext());
|
||||
handlerMapping.setApplicationContext(cxt);
|
||||
handlerMapping.setEmbeddedValueResolver(new StaticStringValueResolver(placeHolderValues));
|
||||
handlerMapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
|
||||
handlerMapping.setUseTrailingSlashMatch(useTrailingSlashPatternMatch);
|
||||
handlerMapping.setOrder(0);
|
||||
@@ -351,7 +372,6 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
if (removeSemicolonContent != null) {
|
||||
handlerMapping.setRemoveSemicolonContent(removeSemicolonContent);
|
||||
}
|
||||
|
||||
return handlerMapping;
|
||||
}
|
||||
|
||||
@@ -427,6 +447,30 @@ public class StandaloneMockMvcBuilder extends DefaultMockMvcBuilder<StandaloneMo
|
||||
}
|
||||
}
|
||||
|
||||
/** A static resolver placeholder for values embedded in request mappings */
|
||||
private static class StaticStringValueResolver implements StringValueResolver {
|
||||
|
||||
private final PropertyPlaceholderHelper helper;
|
||||
|
||||
private final PlaceholderResolver resolver;
|
||||
|
||||
|
||||
public StaticStringValueResolver(final Map<String, String> values) {
|
||||
this.helper = new PropertyPlaceholderHelper("${", "}", ":", false);
|
||||
this.resolver = new PlaceholderResolver() {
|
||||
@Override
|
||||
public String resolvePlaceholder(String placeholderName) {
|
||||
return values.get(placeholderName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveStringValue(String strVal) throws BeansException {
|
||||
return this.helper.replacePlaceholders(strVal, this.resolver);
|
||||
}
|
||||
}
|
||||
|
||||
/** A {@link ViewResolver} that always returns same View */
|
||||
private static class StaticViewResolver implements ViewResolver {
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.setup;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.test.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class StandaloneMockMvcBuilderTests {
|
||||
|
||||
|
||||
// SPR-10825
|
||||
|
||||
@Test
|
||||
public void placeHoldersInRequestMapping() throws Exception {
|
||||
|
||||
StubWebApplicationContext cxt = new StubWebApplicationContext(new MockServletContext());
|
||||
StandaloneMockMvcBuilder builder = new StandaloneMockMvcBuilder(new PlaceholderController());
|
||||
builder.addPlaceHolderValues("sys.login.ajax", "/foo");
|
||||
builder.initWebAppContext(cxt);
|
||||
|
||||
RequestMappingHandlerMapping hm = cxt.getBean(RequestMappingHandlerMapping.class);
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
|
||||
HandlerExecutionChain chain = hm.getHandler(request);
|
||||
|
||||
assertNotNull(chain);
|
||||
assertEquals("handleWithPlaceholders", ((HandlerMethod) chain.getHandler()).getMethod().getName());
|
||||
}
|
||||
|
||||
|
||||
@Controller
|
||||
private static class PlaceholderController {
|
||||
|
||||
@RequestMapping(value = "${sys.login.ajax}")
|
||||
private void handleWithPlaceholders() { }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user