Proper support for Root WAC in Spring MVC Test
The modifications to DefaultMockMvcBuilder performed in conjunction with SPR-12553 introduced a breaking change: the WebApplicationContext supplied to DefaultMockMvcBuilder's constructor was *always* stored in the ServletContext as the root WebApplicationContext, overwriting a root WebApplicationContext that had been set by the user or by the Spring TestContext Framework (TCF) -- for example, in AbstractGenericWebContextLoader. Consequently, the changes in SPR-12553 cause tests that use @ContextHierarchy to fail if web components rely on the correct WebApplicationContext being stored under the WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key. This commit reverts the breaking changes introduced in SPR-12553: if the root WebApplicationContext has already been set in the ServletContext of the WebApplicationContext supplied to DefaultMockMvcBuilder, no action is taken. Furthermore, this commit introduces new code to address the initial intent of SPR-12553. Specifically, if the root WebApplicationContext has NOT been set in the ServletContext of the WebApplicationContext supplied to DefaultMockMvcBuilder, the application context hierarchy will be traversed in search of the root WebApplicationContext, and the root WebApplicationContext will then be stored under the ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key. Issue: SPR-13075, SPR-12553
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -18,16 +18,25 @@ package org.springframework.test.web.servlet.setup;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
/**
|
||||
* An concrete implementation of {@link AbstractMockMvcBuilder} that simply
|
||||
* provides the WebApplicationContext given to it as a constructor argument.
|
||||
* A concrete implementation of {@link AbstractMockMvcBuilder} that provides
|
||||
* the {@link WebApplicationContext} supplied to it as a constructor argument.
|
||||
*
|
||||
* <p>In addition, if the {@link ServletContext} in the supplied
|
||||
* {@code WebApplicationContext} does not contain an entry for the
|
||||
* {@link WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE}
|
||||
* key, the root {@code WebApplicationContext} will be detected and stored
|
||||
* in the {@code ServletContext} under the
|
||||
* {@code ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} key.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Rob Winch
|
||||
* @author Sebastien Deleuze
|
||||
* @author Sam Brannen
|
||||
* @since 3.2
|
||||
*/
|
||||
public class DefaultMockMvcBuilder extends AbstractMockMvcBuilder<DefaultMockMvcBuilder> {
|
||||
@@ -45,11 +54,25 @@ public class DefaultMockMvcBuilder extends AbstractMockMvcBuilder<DefaultMockMvc
|
||||
this.webAppContext = webAppContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected WebApplicationContext initWebAppContext() {
|
||||
|
||||
ServletContext servletContext = this.webAppContext.getServletContext();
|
||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.webAppContext);
|
||||
ApplicationContext rootWac = WebApplicationContextUtils.getWebApplicationContext(servletContext);
|
||||
|
||||
if (rootWac == null) {
|
||||
rootWac = this.webAppContext;
|
||||
ApplicationContext parent = this.webAppContext.getParent();
|
||||
while (parent != null) {
|
||||
if (parent instanceof WebApplicationContext && !(parent.getParent() instanceof WebApplicationContext)) {
|
||||
rootWac = parent;
|
||||
break;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootWac);
|
||||
}
|
||||
|
||||
return this.webAppContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,20 +65,20 @@ import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
|
||||
/**
|
||||
* A MockMvcBuilder that accepts {@code @Controller} registrations thus allowing
|
||||
* full control over the instantiation and the initialization of controllers and
|
||||
* their dependencies similar to plain unit tests, and also making it possible
|
||||
* to test one controller at a time.
|
||||
* A {@code MockMvcBuilder} that accepts {@code @Controller} registrations
|
||||
* thus allowing full control over the instantiation and initialization of
|
||||
* controllers and their dependencies similar to plain unit tests, and also
|
||||
* making it possible to test one controller at a time.
|
||||
*
|
||||
* <p>This builder creates the minimum infrastructure required by the
|
||||
* {@link DispatcherServlet} to serve requests with annotated controllers and
|
||||
* also provides methods to customize it. The resulting configuration and
|
||||
* customizations possible are equivalent to using the MVC Java config except
|
||||
* also provides methods for customization. The resulting configuration and
|
||||
* customization options are equivalent to using MVC Java config except
|
||||
* using builder style methods.
|
||||
*
|
||||
* <p>To configure view resolution, either select a "fixed" view to use for every
|
||||
* performed request (see {@link #setSingleView(View)}) or provide a list of
|
||||
* {@code ViewResolver}'s, see {@link #setViewResolvers(ViewResolver...)}.
|
||||
* request performed (see {@link #setSingleView(View)}) or provide a list of
|
||||
* {@code ViewResolver}s (see {@link #setViewResolvers(ViewResolver...)}).
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.2
|
||||
|
||||
Reference in New Issue
Block a user