diff --git a/spring-test/src/main/java/org/springframework/test/context/web/ServletTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/web/ServletTestExecutionListener.java index e58840a93a4..5b6a08a4f8f 100644 --- a/spring-test/src/main/java/org/springframework/test/context/web/ServletTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/web/ServletTestExecutionListener.java @@ -25,12 +25,14 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Conventions; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.test.context.TestContext; import org.springframework.test.context.TestExecutionListener; import org.springframework.test.context.support.AbstractTestExecutionListener; +import org.springframework.util.Assert; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletWebRequest; @@ -52,8 +54,9 @@ import org.springframework.web.context.request.ServletWebRequest; * #afterTestMethod(TestContext) cleans up} thread-local state. * *
Note that {@code ServletTestExecutionListener} is enabled by default but - * takes no action if the {@link ApplicationContext} loaded for the current test - * is not a {@link WebApplicationContext}. + * generally takes no action if the {@linkplain TestContext#getTestClass() test + * class} is not annotated with {@link WebAppConfiguration @WebAppConfiguration}. + * See the Javadoc for individual methods in this class for details. * * @author Sam Brannen * @since 3.2 @@ -76,7 +79,9 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener /** * Sets up thread-local state during the test instance preparation - * callback phase via Spring Web's {@link RequestContextHolder}. + * callback phase via Spring Web's {@link RequestContextHolder}, but only if + * the {@linkplain TestContext#getTestClass() test class} is annotated with + * {@link WebAppConfiguration @WebAppConfiguration}. * * @see TestExecutionListener#prepareTestInstance(TestContext) * @see #setUpRequestContextIfNecessary(TestContext) @@ -88,7 +93,9 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener /** * Sets up thread-local state before each test method via Spring Web's - * {@link RequestContextHolder}. + * {@link RequestContextHolder}, but only if the + * {@linkplain TestContext#getTestClass() test class} is annotated with + * {@link WebAppConfiguration @WebAppConfiguration}. * * @see TestExecutionListener#beforeTestMethod(TestContext) * @see #setUpRequestContextIfNecessary(TestContext) @@ -101,7 +108,11 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener /** * Cleans up thread-local state after each test method by {@linkplain * RequestContextHolder#resetRequestAttributes() resetting} Spring Web's - * {@code RequestContextHolder}. + * {@code RequestContextHolder}, but only if the {@link + * #RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE} in the supplied {@code TestContext} + * has a value of {@link Boolean#TRUE}. + *
The {@link #RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE} will be
+ * subsequently removed from the test context, regardless of its value.
*
* @see TestExecutionListener#afterTestMethod(TestContext)
*/
@@ -112,22 +123,27 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener
logger.debug(String.format("Resetting RequestContextHolder for test context %s.", testContext));
}
RequestContextHolder.resetRequestAttributes();
- testContext.removeAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE);
}
+ testContext.removeAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE);
+ }
+
+ private boolean notAnnotatedWithWebAppConfiguration(TestContext testContext) {
+ return AnnotationUtils.findAnnotation(testContext.getTestClass(), WebAppConfiguration.class) == null;
}
private void setUpRequestContextIfNecessary(TestContext testContext) {
+ if (notAnnotatedWithWebAppConfiguration(testContext)) {
+ return;
+ }
ApplicationContext context = testContext.getApplicationContext();
if (context instanceof WebApplicationContext) {
WebApplicationContext wac = (WebApplicationContext) context;
ServletContext servletContext = wac.getServletContext();
- if (!(servletContext instanceof MockServletContext)) {
- throw new IllegalStateException(String.format(
- "The WebApplicationContext for test context %s must be configured with a MockServletContext.",
- testContext));
- }
+ Assert.state(servletContext instanceof MockServletContext, String.format(
+ "The WebApplicationContext for test context %s must be configured with a MockServletContext.",
+ testContext));
if (logger.isDebugEnabled()) {
logger.debug(String.format(
@@ -135,22 +151,20 @@ public class ServletTestExecutionListener extends AbstractTestExecutionListener
testContext));
}
- if (RequestContextHolder.getRequestAttributes() == null) {
- MockServletContext mockServletContext = (MockServletContext) servletContext;
- MockHttpServletRequest request = new MockHttpServletRequest(mockServletContext);
- MockHttpServletResponse response = new MockHttpServletResponse();
- ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
-
- RequestContextHolder.setRequestAttributes(servletWebRequest);
- testContext.setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE);
-
- if (wac instanceof ConfigurableApplicationContext) {
- @SuppressWarnings("resource")
- ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) wac;
- ConfigurableListableBeanFactory bf = configurableApplicationContext.getBeanFactory();
- bf.registerResolvableDependency(MockHttpServletResponse.class, response);
- bf.registerResolvableDependency(ServletWebRequest.class, servletWebRequest);
- }
+ MockServletContext mockServletContext = (MockServletContext) servletContext;
+ MockHttpServletRequest request = new MockHttpServletRequest(mockServletContext);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ServletWebRequest servletWebRequest = new ServletWebRequest(request, response);
+
+ RequestContextHolder.setRequestAttributes(servletWebRequest);
+ testContext.setAttribute(RESET_REQUEST_CONTEXT_HOLDER_ATTRIBUTE, Boolean.TRUE);
+
+ if (wac instanceof ConfigurableApplicationContext) {
+ @SuppressWarnings("resource")
+ ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) wac;
+ ConfigurableListableBeanFactory bf = configurableApplicationContext.getBeanFactory();
+ bf.registerResolvableDependency(MockHttpServletResponse.class, response);
+ bf.registerResolvableDependency(ServletWebRequest.class, servletWebRequest);
}
}
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java
index b6581a7e315..9972c42c7cb 100644
--- a/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/web/ServletTestExecutionListenerTests.java
@@ -18,6 +18,7 @@ package org.springframework.test.context.web;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -48,6 +49,14 @@ public class ServletTestExecutionListenerTests {
private final ServletTestExecutionListener listener = new ServletTestExecutionListener();
+ private void assertAttributesAvailable() {
+ assertNotNull("request attributes should be available", RequestContextHolder.getRequestAttributes());
+ }
+
+ private void assertAttributesNotAvailable() {
+ assertNull("request attributes should not be available", RequestContextHolder.getRequestAttributes());
+ }
+
private void assertAttributeExists() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
assertNotNull("request attributes should exist", requestAttributes);
@@ -80,9 +89,13 @@ public class ServletTestExecutionListenerTests {
}
@Test
- public void withStandardApplicationContext() throws Exception {
+ public void standardApplicationContext() throws Exception {
+ Mockito.