Populate RequestAttributes before invoking Filters in MockMvc

When using the Spring TestContext Framework (TCF) to load a
WebApplicationContext and the Spring MVC Test Framework (MockMvc) to
test a controller, two instances of MockHttpServletRequest will be
created. Due to an ordering issue with regard to population of the
RequestAttributes, it is therefore possible that a filter accesses the
mocked request managed by the TCF, while the controller accesses the
mocked request managed by MockMvc, and this leads to test failures if
the controller expects data from the filter to be present in the
request.

This commit fixes this bug by ensuring that the RequestAttributes
backed by the mocked request managed by MockMvc are stored in the
RequestContextHolder before any filters are invoked by MockMvc.

Issue: SPR-13217
This commit is contained in:
Sam Brannen
2015-07-10 17:21:46 +03:00
parent 3d951755fa
commit 9c46228a97
2 changed files with 62 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2015 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.
@@ -26,6 +26,8 @@ import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* <strong>Main entry point for server-side Spring MVC test support.</strong>
@@ -48,6 +50,7 @@ import org.springframework.util.Assert;
*
* @author Rossen Stoyanchev
* @author Rob Winch
* @author Sam Brannen
* @since 3.2
*/
public final class MockMvc {
@@ -140,6 +143,10 @@ public final class MockMvc {
final MvcResult mvcResult = new DefaultMvcResult(request, response);
request.setAttribute(MVC_RESULT_ATTRIBUTE, mvcResult);
// [SPR-13217] Simulate RequestContextFilter to ensure that RequestAttributes are
// populated before filters are invoked.
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request, response));
MockFilterChain filterChain = new MockFilterChain(this.servlet, this.filters);
filterChain.doFilter(request, response);