<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>James Farrell</title>
	<atom:link href="http://jamesfarrell129.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jamesfarrell129.wordpress.com</link>
	<description>Agile Java developer</description>
	<lastBuildDate>Thu, 21 Apr 2011 09:24:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jamesfarrell129.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>James Farrell</title>
		<link>http://jamesfarrell129.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jamesfarrell129.wordpress.com/osd.xml" title="James Farrell" />
	<atom:link rel='hub' href='http://jamesfarrell129.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Integration Testing for Spring Portlet MVC</title>
		<link>http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/</link>
		<comments>http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 15:23:08 +0000</pubDate>
		<dc:creator>jamesfarrell129</dc:creator>
				<category><![CDATA[Portlet MVC]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://jamesfarrell129.wordpress.com/?p=4</guid>
		<description><![CDATA[I recently saw a post about testing Spring MVC controllers outside of a container.  I&#8217;ve been working at OpenCredo on a portlet application over the last few months, and although a bit late in the day for this project, I figured something along these lines would be of great benefit for any future development.  So <a href="http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/" class="excerpt-more-link">[&#8230;]</a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jamesfarrell129.wordpress.com&amp;blog=22349211&amp;post=4&amp;subd=jamesfarrell129&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recently saw a post about <a href="http://tedyoung.me/2011/02/14/spring-mvc-integration-testing-controllers/">testing Spring MVC controllers outside of a container</a>.  I&#8217;ve been working at <a href="http://www.opencredo.com/" target="_blank">OpenCredo</a> on a portlet application over the last few months, and although a bit late in the day for this project, I figured something along these lines would be of great benefit for any future development.  So taking some of the ideas off of that blog, I started putting together a similar concept for use with the <a href="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/portlet.html">Spring Portlet MVC</a>.</p>
<p>The goal of the exercise was to test a bit further around the portlet controllers; its one thing to write a unit test, to check a particular method is working as expected, but in a controller with 5 or 6 different action methods, I wanted to ensure that for a known set of parameters in the request, the correct controller method would be executed.</p>
<h2>Mocking up a ContextLoader</h2>
<p>The first step is creating a mock <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/context/ContextLoader.html">ContextLoader</a> to set up the Portlet environment.  We create MockPortletContext and MockPortletConfig objects, using our MockWebApplication for configuration.  Then we create an instance of <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/portlet/DispatcherPortlet.html">DispatcherPortlet</a> and configure it.</p>
<p>Notice the use of a <code>MockViewResolver</code>:</p>
<p style="padding-left:30px;">final ViewResolver viewResolver = new MockViewResolver();<br />
portletApplicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {</p>
<p style="padding-left:60px;">public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {</p>
<p style="padding-left:90px;">beanFactory.registerResolvableDependency(DispatcherPortlet.class, dispatcherPortlet);<br />
beanFactory.registerResolvableDependency(ViewResolver.class, viewResolver);</p>
<p style="padding-left:60px;">}</p>
<p style="padding-left:30px;">});</p>
<p>This is a simple <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/servlet/ViewResolver.html">ViewResolver</a> implementation that stores a view name and model, so we can check them later on for testing purposes.  This means we can ignore whatever view technology we are using for the tests.</p>
<h2>Some example tests</h2>
<p>I found a <a href="http://code.google.com/p/spring-portlet-sample/source/browse/">Spring portlet application</a> project to use as a basis for some tests, and made a few tweaks.  The <a href="https://github.com/jamesfarrell/spring-portlet-sample">complete source code</a> can be found in GitHub.  This gives us a <code>BooksController</code></p>
<p style="padding-left:30px;">@Controller(&#8220;bookController&#8221;)<br />
@RequestMapping(&#8220;VIEW&#8221;)<br />
@SessionAttributes(&#8220;book&#8221;)<br />
public class BooksController {</p>
<p style="padding-left:60px;">private BookService bookService;<br />
@Autowired<br />
public BooksController(@Qualifier(&#8220;bookService&#8221;) BookService bookService) {</p>
<p style="padding-left:90px;">this.bookService = bookService;</p>
<p style="padding-left:60px;">}</p>
<p style="padding-left:30px;">}</p>
<p>along with its autowired service</p>
<p style="padding-left:30px;">@Service(value=&#8221;bookService&#8221;)<br />
public class BookServiceImpl extends ApplicationObjectSupport implements BookService {<br />
&#8230;<br />
}</p>
<p>To test this controller I created a JUnit class and injected the <code>DispatcherPortlet</code> and <code>ViewResolver</code> from the application context.</p>
<p style="padding-left:30px;">@RunWith(SpringJUnit4ClassRunner.class)<br />
@ContextConfiguration(locations={&#8220;classpath:applicationContext-test.xml&#8221;},</p>
<p style="padding-left:90px;">loader=MockWebApplicationContextLoader.class)</p>
<p style="padding-left:30px;">@MockWebApplication(name=&#8221;booksPortlet&#8221;)<br />
public class BooksControllerIntegrationTest {</p>
<p style="padding-left:60px;">@Autowired<br />
private DispatcherPortlet dispatcherPortlet;<br />
@Autowired<br />
private MockViewResolver viewResolver;<br />
@Autowired<br />
@Qualifier(&#8220;bookService&#8221;)<br />
private BookService bookService;</p>
<p style="padding-left:30px;">}</p>
<p>Since the <code>BooksController</code> has listed <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/bind/annotation/SessionAttributes.html">@SessionAttributes</a>, we need to add a Book attribute to the portlet session for each request:</p>
<p style="padding-left:30px;">private void setupRequestSession(PortletRequest request) {</p>
<p style="padding-left:60px;">Book book = new Book(AUTHOR, TITLE, COUNT);<br />
book.setKey(KEY);<br />
PortletUtils.setSessionAttribute(request, &#8220;book&#8221;, book);</p>
<p style="padding-left:30px;">}</p>
<p>This then allows us to set some expected parameters, call <code>dispatcherPortlet.render(request, response)</code> or <code>dispatcherPortlet.processAction(request, response)</code>, and ensure the correct action or render method gets called.</p>
<h3>Testing Render Methods</h3>
<p>In our example, there are four render methods in the controller under test; setting no extra parameters in the render request should call the <code>viewListOfBooks</code> method.  We can test this simply:</p>
<p style="padding-left:30px;">@Test<br />
public void viewListOfBooks() throws ServletException, IOException, PortletException {</p>
<p style="padding-left:60px;">MockRenderRequest request = new MockRenderRequest();<br />
setupRequestSession(request);<br />
dispatcherPortlet.render(request, new MockRenderResponse());</p>
<p style="padding-left:30px;">}</p>
<p>But if we want to trigger a different render method, some parameters will need adding to the request.  Luckily we can use <code>addParameter()</code> on <code>MockRenderRequest</code>:</p>
<p style="padding-left:30px;">@Test<br />
public void viewBook() throws ServletException, IOException, PortletException {</p>
<p style="padding-left:60px;">final Integer TEST_ID = 2;<br />
MockRenderRequest request = new MockRenderRequest();<br />
setupRequestSession(request);<br />
request.addParameter(&#8220;book&#8221;, TEST_ID.toString());<br />
request.addParameter(&#8220;action&#8221;, &#8220;viewBook&#8221;);<br />
dispatcherPortlet.render(request, new MockRenderResponse());</p>
<p style="padding-left:30px;">}</p>
<p>With render methods, the first thing to check is that we get the expected view name returned.  The <code>DispatcherPortlet</code> itself will usually handle this, but for test purposes we can use our <code>MockViewResolver</code>:</p>
<p style="padding-left:30px;">assertEquals(&#8220;Incorrect view name found&#8221;, &#8220;books&#8221;, viewResolver.getViewName());</p>
<p>We may also want to check what gets added to the Spring <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/ui/Model.html">Model</a>; this will be stored as a request attribute under <code>ViewRendererServlet.MODEL_ATTRIBUTE</code>, so we can check that expected values have been added:</p>
<p style="padding-left:30px;">assertNotNull(&#8220;No UI model found&#8221;, request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE));<br />
ModelMap model = (ModelMap) request.getAttribute(ViewRendererServlet.MODEL_ATTRIBUTE);</p>
<p>assertNotNull(&#8220;Null list of books found in model&#8221;, model.get(&#8220;books&#8221;));<br />
assertTrue(&#8220;List of books found in model was not a Sorted Set&#8221;, model.get(&#8220;books&#8221;) instanceof SortedSet);<br />
SortedSet&lt;Book&gt; modelBooks = (SortedSet&lt;Book&gt;) model.get(&#8220;books&#8221;);<br />
assertEquals(&#8220;Incorrect number of books found in model&#8221;, bookService.getAllBooks().size(), modelBooks.size());</p>
<h3>Testing Action Methods</h3>
<p>The action methods generally require more request parameters to be added. For instance, the <code>deleteBook</code> method</p>
<p style="padding-left:30px;">@RequestMapping(params = &#8220;action=deleteBook&#8221;)<br />
public void deleteBook(ActionResponse response, @RequestParam(&#8220;book&#8221;) Integer id) {</p>
<p style="padding-left:60px;">bookService.deleteBook(id);</p>
<p style="padding-left:30px;">}</p>
<p>will need request parameters</p>
<p style="padding-left:30px;">request.addParameter(&#8220;action&#8221;, &#8220;deleteBook&#8221;);<br />
request.addParameter(&#8220;book&#8221;, &#8220;2&#8243;);</p>
<p>There can also be action methods with formal parameters annotated as <a href="http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/bind/annotation/ModelAttribute.html">@ModelAttribute</a>, such as <code>submitAddBookFormPage</code>:</p>
<p style="padding-left:30px;">@RequestMapping(params = &#8220;action=addBook&#8221;)<br />
public void submitAddBookFormPage(ActionRequest request, ActionResponse response, @ModelAttribute(&#8220;book&#8221;) Book book,</p>
<p style="padding-left:120px;">BindingResult result, @RequestParam(&#8220;_page&#8221;) int currentPage, Model model) {</p>
<p style="padding-left:30px;">}</p>
<p>In this case we&#8217;ve already covered the &#8220;book&#8221; parameter, adding it as a portlet session attribute &#8211; so testing this method we just need to add</p>
<p style="padding-left:30px;">request.addParameter(&#8220;action&#8221;, &#8220;addBook&#8221;);<br />
request.addParameter(&#8220;_page&#8221;, &#8220;1&#8243;);</p>
<p>These tests generally check the existing state from the injected BookService, call the <code>processAction()</code> method of the <code>dispatcherPortlet</code>, then re-check the BookService to make sure the correct update has occurred.</p>
<h3>Testing the flow from Action to Render methods</h3>
<p>One last thing we can do is to run an action, take the render parameters set by the action, and check the correct render method is then called.  Using the <code>editBook</code> as an example, we can set-up the action request as per the previous test, then use the response from <code>processAction()</code> to set render parameters:</p>
<p style="padding-left:30px;">renderRequest.setParameters(actionResponse.getRenderParameterMap());</p>
<p>We can then call <code>render()</code>, and check both the returned view, and the book service to ensure the action has completed as expected.</p>
<h2>Conclusions</h2>
<p>Hopefully this solution for integration testing will help people who are currently struggling with Portlet development.</p>
<p>The biggest pain point I have found is that, once unit tests have been run to ensure a controller is working correctly, it then takes time to deploy a portal application before the exact workings can be determined.  Whilst tools such as <a href="http://openportal.sourceforge.net/">Open Portal</a> can help with this, it will still be easier and much more efficient for a developer to find any errors using tests that can be run through their IDE.</p>
<h3>References</h3>
<p>I was initially inspired by <a href="http://www.vijedi.net/2009/integration-testing-spring-mvc-annotated-controllers/">this post about writing integration tests</a> for MVC controllers.</p>
<p>Whilst looking for portlet code examples &#8211; something that seems to be sorely lacking &#8211; I stumbled across the <a href="http://portlets-in-action.blogspot.com/2010/02/spring-30-portlet-mvc.html">Portlets in Action blog</a> and a related <a href="http://books.dzone.com/articles/spring-30-portlet-mvc-part-2">article on annotated controllers</a>, which helped me further my knowledge of the various annotations.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jamesfarrell129.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jamesfarrell129.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jamesfarrell129.wordpress.com/4/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jamesfarrell129.wordpress.com&amp;blog=22349211&amp;post=4&amp;subd=jamesfarrell129&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jamesfarrell129.wordpress.com/2011/04/20/integration-testing-for-spring-portlet-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7745b99d1829b50fe8a2450b86bcdb3d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jamesfarrell129</media:title>
		</media:content>
	</item>
	</channel>
</rss>
