所以,基本上,我在请求的过滤器中设置的属性,不能在 ClientSessionServiceImpl 中读取,因为那里注入了不同的 MockHttpServletRequest 实例。
这是关于 Spring 何时RequestAttributes
填充到RequestContextHolder
. 在生产中,我假设您正在配置 aRequestContextFilter
或 a RequestContextListener
。
无论如何,RequestContextFilter
在您的测试中手动添加一个实例到过滤器链的前面将解决问题。
mockMvc = MockMvcBuilders
.webAppContextSetup(this.wac)
.addFilters(new RequestContextFilter(), testFilterChain)
.build();
请注意,这将成为 Spring Framework 4.2 中的默认行为:模拟的代码RequestContextFilter
将直接在MockMvc
. 有关详细信息,请参阅 JIRA 问题SPR-13217。
顺便说一句,不支持配置由MockHttpServletRequest
创建的。ServletTestExecutionListener
如果您正在使用MockMvc
它,您应该通过RequestBuilders
.
但是,话虽如此,如果您确实需要修改ServletTestExecutionListener
手动创建的模拟请求,然后再使用它MockMvc
,您可以在项目中创建以下类:
package org.springframework.test.web.servlet.request;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* Patched version of {@link MockHttpServletRequestBuilder}.
*
* @author Sam Brannen
* @since 4.2
*/
public class PatchedMockHttpServletRequestBuilder extends MockHttpServletRequestBuilder {
public static MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables) {
return new PatchedMockHttpServletRequestBuilder(HttpMethod.GET, urlTemplate, urlVariables);
}
public PatchedMockHttpServletRequestBuilder(HttpMethod httpMethod, String urlTemplate, Object... urlVariables) {
super(httpMethod, urlTemplate, urlVariables);
}
/**
* Create a {@link MockHttpServletRequest}.
* <p>If an instance of {@code MockHttpServletRequest} is available via
* the {@link RequestAttributes} bound to the current thread in
* {@link RequestContextHolder}, this method simply returns that instance.
* <p>Otherwise, this method creates a new {@code MockHttpServletRequest}
* based on the supplied {@link ServletContext}.
* <p>Can be overridden in subclasses.
* @see RequestContextHolder#getRequestAttributes()
* @see ServletRequestAttributes
*/
@Override
protected MockHttpServletRequest createServletRequest(ServletContext servletContext) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
if (request instanceof MockHttpServletRequest) {
return (MockHttpServletRequest) request;
}
}
return new MockHttpServletRequest(servletContext);
}
}
注意:必须在org.springframework.test.web.servlet.request
包装内;否则,它无法扩展MockHttpServletRequestBuilder
所需的内容。
然后,使用get()
from 方法PatchedMockHttpServletRequestBuilder
而不是 from MockMvcRequestBuilders
,一切都应该如你所愿!
显然,上面的例子重新实现 get()
了,但是你自然可以对post()
等做同样的事情。
仅供参考:我最终可能会将上述修补版本提交createServletRequest()
给 Spring Framework 4.2.x(请参阅 JIRA 问题SPR-13211)。
问候,
Sam(Spring TestContext 框架的作者)