<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=kris2008" rel="nofollow">Harikrishna Kollli</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-5874?redirect=false" rel="nofollow">SPR-5874</a></strong> and commented</p>
<hr>
<p dir="auto"><strong>Affects:</strong> 3.0 M3</p>
<p dir="auto"><strong>Reference URL:</strong> <a href="http://forum.springsource.org/showthread.php?t=74021" rel="nofollow">http://forum.springsource.org/showthread.php?t=74021</a></p>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398095925" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/10545" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/10545/hovercard" href="https://github.com/spring-projects/spring-framework/issues/10545">#10545</a> issue with the form tag. The Inner tags not able to access the name of the command object via the  PageContext in partial page rendering (<em><strong>"is duplicated by"</strong></em>)</li>
</ul>
<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=geoffm" rel="nofollow">Geoff Metselaar</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-5243?redirect=false" rel="nofollow">SPR-5243</a></strong> and commented</p>
<h4 dir="auto">Status Quo</h4>
<p dir="auto">When the <em>Spring TestContext Framework</em> was introduced in Spring 2.5, it supported loading an <code class="notranslate">ApplicationContext</code> from either XML or Java Properties files. Spring 3.1 introduced support for loading an <code class="notranslate">ApplicationContext</code> from <em>annotated classes</em> (e.g., <code class="notranslate">@Configuration</code> classes).</p>
<p dir="auto">The underlying implementation for the existing support creates a <code class="notranslate">GenericApplicationContext</code>; however, a <code class="notranslate">GenericApplicationContext</code> is not suitable for testing a web application since a web application relies on an implementation of <code class="notranslate">WebApplicationContext</code> (<em>WAC</em>).</p>
<p dir="auto">In order to integration test Spring-powered web applications the Spring TestContext Framework needs to be able to load a <code class="notranslate">WebApplicationContext</code>, either from XML configuration files or from annotated classes. Furthermore, the <code class="notranslate">ServletContext</code> used by such a WAC needs to be configurable within tests, and common context hierarchies must be supported (e.g., <em>root</em> and <em>dispatcher</em> WACs in a parent-child relationship).</p>
<h6 dir="auto">Original Author's Description</h6>
<p dir="auto">While writing some MVC integration tests, context errors were thrown when loading an <code class="notranslate">XmlViewResolver</code> and when attempting to recover command object property validation errors using the <code class="notranslate">RequestContext</code>. The reason is that each of these requires access to a <code class="notranslate">WebApplicationContext</code>, not a  <code class="notranslate">GenericApplicationContext</code> which the TestContext framework makes available by default.</p>
<hr>
<h4 dir="auto">Goals</h4>
<ul dir="auto">
<li>Introduce an annotation that allows developers to configure a mock <code class="notranslate">ServletContext</code> from within integration tests.</li>
<li>Introduce <code class="notranslate">SmartContextLoaders</code> that can load <code class="notranslate">WebApplicationContexts</code> from either XML or annotated classes, using the configured mock <code class="notranslate">ServletContext</code>.</li>
<li>Provide a means for developers to access the mocks for the <code class="notranslate">HttpServletRequest</code> and <code class="notranslate">HttpServletResponse</code> objects and ensure that thread-local state in Spring MVC is kept in sync with these mock objects.</li>
<li>Ensure that metadata used to create the <code class="notranslate">WebApplicationContext</code> (e.g., <code class="notranslate">ServletContext</code> path) is used to define the unique application context cache key.</li>
</ul>
<hr>
<h4 dir="auto">Deliverables</h4>
<ol class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Implement a <code class="notranslate">SmartContextLoader</code> that loads a <code class="notranslate">WebApplicationContext</code> from XML resource locations defined via <code class="notranslate">@ContextConfiguration</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Implement a <code class="notranslate">SmartContextLoader</code> that loads a <code class="notranslate">WebApplicationContext</code> from annotated classes defined via <code class="notranslate">@ContextConfiguration</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Introduce a new class-level <code class="notranslate">@WebAppConfiguration</code> annotation that allows for configuration of the <code class="notranslate">ServletContext</code> base resource path, using Spring's <code class="notranslate">Resource</code> abstraction
<ul dir="auto">
<li>see <code class="notranslate">ContextMockMvcBuilder.configureWebAppRootDir()</code> from <code class="notranslate">spring-test-mvc</code></li>
<li>the base path must be filesystem-based by default, in contrast to the <code class="notranslate">locations</code> attribute in <code class="notranslate">@ContextConfiguration</code> which is classpath-based</li>
<li>the base path should default to <em>"src/main/webapp"</em>, which follows the Maven convention</li>
<li>determine if <code class="notranslate">@WebAppConfiguration</code> should be <em>inherited</em> (i.e., annotated with <code class="notranslate">@Inherited</code>), keeping in mind that the top-level context in an EAR would not be a WAC</li>
</ul>
</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Ensure that the two newly introduced <code class="notranslate">SmartContextLoader</code> implementations create a <code class="notranslate">MockServletContext</code> on demand (i.e., if a root WAC), when the WAC is loaded, and set the <code class="notranslate">MockServletContext</code> as the <code class="notranslate">ServletContext</code> in the application contexts that they load</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Set a loaded context as the <code class="notranslate">ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</code> in the <code class="notranslate">MockServletContext</code> when context hierarchies are not used</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Introduce a subclass of <code class="notranslate">MergedContextConfiguration</code> specific for web apps (e.g., <code class="notranslate">WebMergedContextConfiguration</code>) that stores the <code class="notranslate">ServletContext</code> base path
<ul dir="auto">
<li>the subclass of MCC must override <code class="notranslate">equals()</code> and <code class="notranslate">hashCode()</code> to include the metadata that uniquely identifies the resulting WAC for proper context caching</li>
<li>the <code class="notranslate">buildMergedContextConfiguration()</code> method in <code class="notranslate">ContextLoaderUtils</code> will likely need to instantiate either a standard <code class="notranslate">MergedContextConfiguration</code> or a <code class="notranslate">WebMergedContextConfiguration</code></li>
</ul>
</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Set up <em>default</em> thread local state via <code class="notranslate">RequestContextHolder</code> before each test method by implementing a new Servlet-specific <code class="notranslate">TestExecutionListener</code>
<ul dir="auto">
<li>by using the <code class="notranslate">MockServletContext</code> already present in the WAC and by creating a <code class="notranslate">MockHttpServletRequest</code>, <code class="notranslate">MockHttpServletResponse</code>, and <code class="notranslate">ServletWebRequest</code> which will be set in the <code class="notranslate">RequestContextHolder</code></li>
</ul>
</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Ensure that the <code class="notranslate">MockServletContext</code>, <code class="notranslate">MockHttpServletRequest</code>, <code class="notranslate">MockHttpServletResponse</code>, and <code class="notranslate">ServletWebRequest</code> can be injected into the test instance (e.g., via <code class="notranslate">@Autowired</code>)</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Clean up thread locals after each test method</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Ensure that the Servlet-specific <code class="notranslate">TestExecutionListener</code> is configured as a default <code class="notranslate">TestExecutionListener</code> <em>before</em> <code class="notranslate">DependencyInjectionTestExecutionListener</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Introduce a new web-specific <code class="notranslate">DelegatingSmartContextLoader</code> to incorporate support for the <code class="notranslate">SmartContextLoader</code> types introduced in this issue and ensure that the correct delegating loader is picked based on the presence or absence of <code class="notranslate">@WebAppConfiguration</code></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Consider being able to accommodate a future request to support mocks for Spring Portlet MVC</li>
</ol>
<hr>
<h4 dir="auto">Pseudocode Examples</h4>
<hr>
<h5 dir="auto">Root WAC with Injected Mocks</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@WebAppConfiguration // path defaults to &quot;file:src/main/webapp&quot;
@ContextConfiguration(&quot;file:src/main/webapp/WEB-INF/applicationContext.xml&quot;)
public class RootWacTests {

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private MockServletContext servletContext;

    @Autowired
    private MockHttpServletRequest request;

    @Autowired
    private MockHttpServletResponse response;

    @Autowired
    private MockHttpSession session;

    @Autowired
    private ServletWebRequest webRequest;

    //...
}"><pre class="notranslate"><code class="notranslate">@WebAppConfiguration // path defaults to "file:src/main/webapp"
@ContextConfiguration("file:src/main/webapp/WEB-INF/applicationContext.xml")
public class RootWacTests {

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private MockServletContext servletContext;

    @Autowired
    private MockHttpServletRequest request;

    @Autowired
    private MockHttpServletResponse response;

    @Autowired
    private MockHttpSession session;

    @Autowired
    private ServletWebRequest webRequest;

    //...
}
</code></pre></div>
<hr>
<h4 dir="auto">Further Resources</h4>
<h5 dir="auto">Blogs and Custom Solutions</h5>
<ul dir="auto">
<li><a href="http://codinghood.blogspot.com/2009/01/spring-integration-testing-for-web.html" rel="nofollow">http://codinghood.blogspot.com/2009/01/spring-integration-testing-for-web.html</a></li>
<li><a href="http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/" rel="nofollow">http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/</a></li>
<li><a href="http://tedyoung.me/2011/02/14/spring-mvc-integration-testing-controllers/" rel="nofollow">http://tedyoung.me/2011/02/14/spring-mvc-integration-testing-controllers/</a></li>
<li><a href="http://code.google.com/p/ted-young/source/browse/trunk/blog.spring-mvc-integration-testing/" rel="nofollow">http://code.google.com/p/ted-young/source/browse/trunk/blog.spring-mvc-integration-testing/</a></li>
</ul>
<h5 dir="auto">Forum Discussions</h5>
<ul dir="auto">
<li><a href="http://forum.springframework.org/showthread.php?p=210177#post210177" rel="nofollow">http://forum.springframework.org/showthread.php?p=210177#post210177</a></li>
<li><a href="http://forum.springframework.org/showthread.php?p=210181" rel="nofollow">http://forum.springframework.org/showthread.php?p=210181</a></li>
<li><a href="http://forum.springsource.org/showthread.php?t=76744" rel="nofollow">http://forum.springsource.org/showthread.php?t=76744</a></li>
</ul>
<hr>
<p dir="auto"><strong>Affects:</strong> 2.5 final, 3.0 GA, 3.1 GA</p>
<p dir="auto"><strong>Attachments:</strong></p>
<ul dir="auto">
<li><a href="https://jira.spring.io/secure/attachment/17654/web_listener_loader.zip" rel="nofollow">web_listener_loader.zip</a> (<em>6.70 kB</em>)</li>
</ul>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398094026" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/10284" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/10284/hovercard" href="https://github.com/spring-projects/spring-framework/issues/10284">#10284</a> Provide support for context hierarchies in the TestContext Framework (<em><strong>"depends on"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398153893" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/14496" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/14496/hovercard" href="https://github.com/spring-projects/spring-framework/issues/14496">#14496</a> Support WebApplicationContext hierarchies in the TestContext Framework (<em><strong>"is depended on by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398086432" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/9265" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/9265/hovercard" href="https://github.com/spring-projects/spring-framework/issues/9265">#9265</a> Provide support for session/request scoped beans for integration testing (<em><strong>"is depended on by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398153899" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/14497" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/14497/hovercard" href="https://github.com/spring-projects/spring-framework/issues/14497">#14497</a> Document WebApplicationContext support in the TestContext Framework (<em><strong>"is depended on by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398095729" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/10519" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/10519/hovercard" href="https://github.com/spring-projects/spring-framework/issues/10519">#10519</a> Provide a ContextLoader for WebApplicationContext (<em><strong>"is duplicated by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398092669" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/10072" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/10072/hovercard" href="https://github.com/spring-projects/spring-framework/issues/10072">#10072</a> Provide test ContextLoader for <code class="notranslate">@ContextConfiguration</code> that creates a WebApplicationContext (<em><strong>"is duplicated by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398087850" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/9436" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/9436/hovercard" href="https://github.com/spring-projects/spring-framework/issues/9436">#9436</a> Make Spring ContextTest annotation support  WebApplicationContext (<em><strong>"is duplicated by"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398153876" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/14492" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/14492/hovercard" href="https://github.com/spring-projects/spring-framework/issues/14492">#14492</a> Add first class support for testing Spring MVC applications</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398154564" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/14588" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/14588/hovercard" href="https://github.com/spring-projects/spring-framework/issues/14588">#14588</a> Introduce bootstrap strategy in the TestContext framework</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398117880" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13849" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13849/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13849">#13849</a> Release 1.0 spring-test-mvc</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398153298" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/14432" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/14432/hovercard" href="https://github.com/spring-projects/spring-framework/issues/14432">#14432</a> ApplicationContext fails to load in tests using Java-based config and WebMvcConfigurationSupport (<em><strong>"supersedes"</strong></em>)</li>
</ul>
<p dir="auto"><strong>Referenced from:</strong> commits <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/461d99af29e8c358ff80ff9ff58a8ea63fe7b670/hovercard" href="https://github.com/spring-projects/spring-framework/commit/461d99af29e8c358ff80ff9ff58a8ea63fe7b670"><tt>461d99a</tt></a>, <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/a281bdbfc528187dcd1214be2d2a97e8482a8a23/hovercard" href="https://github.com/spring-projects/spring-framework/commit/a281bdbfc528187dcd1214be2d2a97e8482a8a23"><tt>a281bdb</tt></a>, <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/90c5f226b62503b492167bcd87361842f73d18b1/hovercard" href="https://github.com/spring-projects/spring-framework/commit/90c5f226b62503b492167bcd87361842f73d18b1"><tt>90c5f22</tt></a>, <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/9937f840d5dbd2be819f45f5101dd6486aa382f6/hovercard" href="https://github.com/spring-projects/spring-framework/commit/9937f840d5dbd2be819f45f5101dd6486aa382f6"><tt>9937f84</tt></a>, <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/a73280ccc8a18e0048351a3f08a51c2b13ec3b45/hovercard" href="https://github.com/spring-projects/spring-framework/commit/a73280ccc8a18e0048351a3f08a51c2b13ec3b45"><tt>a73280c</tt></a>, <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/spring-projects/spring-framework/commit/21ebbb9c028c5ac05f9d541d87b53b08bb021818/hovercard" href="https://github.com/spring-projects/spring-framework/commit/21ebbb9c028c5ac05f9d541d87b53b08bb021818"><tt>21ebbb9</tt></a></p>
<p dir="auto">30 votes, 29 watchers</p>