<?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/"
	>

<channel>
	<title>Gojko Adzic &#187; web</title>
	<atom:link href="http://gojko.net/tag/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://gojko.net</link>
	<description>Building software that matters</description>
	<lastBuildDate>Tue, 31 Jan 2012 09:07:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>QCon London 2009: How web is changing software architecture</title>
		<link>http://gojko.net/2009/03/12/qcon-london-2009-how-web-is-changing-software-architecture/</link>
		<comments>http://gojko.net/2009/03/12/qcon-london-2009-how-web-is-changing-software-architecture/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 10:06:48 +0000</pubDate>
		<dc:creator>gojko</dc:creator>
				<category><![CDATA[news]]></category>
		<category><![CDATA[qcon]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gojko.net/?p=782</guid>
		<description><![CDATA[Dion Hinchcliffe presented a keynote titled Transforming Software Architecture with Web as Platform today at QCon London 2009 conference, focusing on how advances in the web space affect software companies and their products. Hinchcliffe started by saying that “no small system can stand sustained contact with a much larger system...]]></description>
			<content:encoded><![CDATA[<p><a href='http://hinchcliffeandcompany.com/'>Dion Hinchcliffe</a> presented a keynote titled <a href='http://qconlondon.com/london-2009/presentation/Transforming+Software+Architecture+with+Web+as+Platform'>Transforming Software Architecture with Web as Platform</a> today at <a href='/tag/qcon'>QCon London 2009</a> conference, focusing on how advances in the web space affect software companies and their products.<span id="more-782"></span></p>
<p>Hinchcliffe started by saying that “no small system can stand sustained contact with a much larger system without being fundamentally changed”, and argued that the since the web is now much bigger than enterprise systems,it has a significant impact on enterprise architectures. </p>
<p>Quoting Dare Obasanjo, Hinchcliffe said that “my web site is bigger than your enterprise”. The biggest IT centres are not in the enterprise, they are web sites. Web is today a software platform bigger than any operating system, with half a billion hosts and “has all your customers, all your competitors and all the ideas and innovation”. However, Hinchcliffe thinks that there are “only a few proven strategies for long-term competitive advantage” and the community has only now figured out how to use it. </p>
<p>As the requirements for modern software architecture, Hinchcliffe pointed out:</p>
<ul>
<li>highly distributed and federated</li>
<li>have a social architecture</li>
<li>built from cutting edge platfoms and parts</li>
<li>have to scale globally</li>
<li>set with expectations that are very high for functionality and low for the cost to develop/own new apps</li>
<li>created with productivity-oriented development tools</li>
</ul>
<p>Enterprise dependencies are now used live with federated online systems, not by linking to libraries.  Hinchcliffe gave an example of clickatell.com, a world leader in mobile messaging which is used as an online service through a HTTP API, not integrated traditionally. Because of that, a big new challenge for software companies is that they need to become very good at operations as well as developing software. </p>
<p>The value in software systems has, according to Hinchcliffe, moved up the stack. It&#8217;s no longer about the processes but about the data. Facebook, Youtube and Google are examples of leading online systems which are based around data, not processes. To get there, software architecture has to be designed for participation. All top online leaders have the architecture designed for participation. Twitter launched with an API straight away, and the majority of its uses comes from the API. Youtube is the biggest video repository in the world but they haven&#8217;t built up the library themselves, they got there through an architecture of participation. Companies like Harley Davidson and IKEA get customers to create the data, organise communities and provide support. The architecture is there to enable that. The World Bank has a developer network.</p>
<p>Another interesting thing is that the expectations of high productivity make software companies make some strange choices, at least from the classic enterprise perspective. Facebook is built in PHP. Twitter is build with Rails. Most enterprise architects would not choose those platforms to build systems as big as Facebook or Twitter. However, these systems are still market leaders. There is an increasing move to assembly and integration over development of the new code. Architectures have to be designed to support rapid change. Flickr adds changes to production sometimes every thirty minutes.  Hinchcliffe said that Flickr is continuously in beta. [Fair enough, but none of those systems actually takes money from people and works with financial accounts. I'm not so convinced that we could keep a transaction processing system in “constant beta”]. </p>
<p>As key advances that are changing the landscape and will change the landscape in the future,  Hinchcliffe pointed out:</p>
<ul>
<li>cloud computing</li>
<li>non-relational databases</li>
<li>new productivity oriented development platforms</li>
</ul>
<p>As the key factors  for success, he pointed out</p>
<ul>
<li>peer production and crowdsourcing</li>
<li>owning your classes of data on the network</li>
<li>using new distribution models to leverage the web as your platform</li>
<li>social systems</li>
<li>opening supply chains and 3rd party sourcing (programmableweb.com)</li>
</ul>
<p><i>I will be covering QCon London 2009 in detail on this blog. Click <a href='/tag/qcon'>here</a> for other news and reviews from the conference</i></p>
]]></content:encoded>
			<wfw:commentRss>http://gojko.net/2009/03/12/qcon-london-2009-how-web-is-changing-software-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to improve testability of web applications</title>
		<link>http://gojko.net/2009/02/03/how-to-improve-testability-of-web-applications/</link>
		<comments>http://gojko.net/2009/02/03/how-to-improve-testability-of-web-applications/#comments</comments>
		<pubDate>Tue, 03 Feb 2009 13:33:04 +0000</pubDate>
		<dc:creator>gojko</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[openspacecode]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[unit testing]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gojko.net/?p=664</guid>
		<description><![CDATA[Last week I participated in the first Openspace Coding Days in London. The event was organised as a series of ad-hoc coding workshops, and I really enjoyed it. I participated in a very interesting workshop on improving testability of web UIs, that later focused particularly on Microsoft&#8217;s new ASP.NET MVC...]]></description>
			<content:encoded><![CDATA[<p><img src="/images/openspacecode.jpg" align="left" style="width:300px; border:1px solid black; margin:5px 5px 5px 5px" />Last week I participated in the first <a href="http://openspacecode.com/">Openspace Coding Days</a> in London. The event was organised as a series of ad-hoc coding workshops, and I really enjoyed it.  I participated in a very interesting workshop on improving testability of web UIs, that later focused particularly on Microsoft&#8217;s new ASP.NET MVC framework. Here are a couple of conclusions we came to:<span id="more-664"></span><br />
<br clear="all" /></p>
<ul>
<li>MVC approach in general helps a lot to make web UIs testable as it allows us to test lots of things below the surface of the UI efficiently, including the controller workflow, and just roll back transactions to make tests repeatable</li>
<li>Comperensive testing above the UI surface (eg through web automation tools) often doesn&#8217;t pay off as scripts take too much time to execute and maintain.</li>
<li>Automation of stuff below the surface leaves us with more time to do exploratory testing, but some basic automated tests still make sense to do through the web ui as well (eg <a href="http://gojko.net/2007/09/25/effective-user-interface-testing/">face saving tests</a>)</li>
<li>Rather than testing the formatting through the UI, a better approach is to move complex formatting away from view templates into helper classes which can be unit tested. This also reduce the stuff you need to test through the Web surface.</li>
</ul>
<h2>ASP.NET MVC specific ideas</h2>
<ul>
<li>The default (web forms) view engine allows you to put arbitrary code in the view, but view rendering cannot be easily unit tested, so this requires discipline and ensuring that view pages contain only display and formatting code. Going back to the one of already mentioned ideas, complex formatting should be moved to helper classes and not be in the view page as well.</li>
<li>ASP.NET MVC doesn&#8217;t really provide any special support for unit testing out of the box. There is no equivalent to Monorail&#8217;s test HTTP contexts. You can still mock out HTTP objects yourself. However, controller methods that don&#8217;t depend on HTTP contexts or sessions can be easily unit tested as normal classes.</li>
<li>Using helpers to generate forms makes views more resilient to change as routes are automatically generated based on class properties. So when you refactor controller method names, form targets and properties get updated automatically.</li>
<li>Similar approach in the controllers is to use the ExpressionHelper from the optional extension package Micrososft.Web.MVC, which enables us to get calculate routes with a lambda expression, generating the URL for a particular action. Using this rather than hard-coding strings makes controllers more resilient to change, as lambda expressions are strongly typed and refactoring friendly.</li>
<li>Although IView has the render method with a Writer argument, because the default WebForms view engine is using HttpContext.Current it ignores the writer and cannot be mocked out. Other view engines do make use of the TextWriter so the view output could be captured for testing purposes from a unit test.</li>
<li>The <a href="http://mvccontrib.org">MVC contrib</a> package has some more additional tools to test routes from unit test tools.</li>
</ul>
<p>We did manage to put together a very simple web application that demonstrates some of these techniques during the workshop, and you can download the source code for that from the <a href="http://code.google.com/p/openspacecode">Open space code</a> subversion repository.</p>
<p>I really enjoyed participating in the Openspace Code workshops and I&#8217;m really looking forward to the next one. Apparently, they are going to be organised every two months. Here are some links to other write-ups:</p>
<ul>
<li><a href="http://alandean.blogspot.com/2009/02/wrapping-up-first-open-space-coding-day.html">Alan Dean</a></li>
<li><a href="http://cantgrokwontgrok.blogspot.com/2009/01/open-space-coding-day-31st-jan-2009.html">Rob Cooper</a></li>
<li><a href="http://kareenascode.blogspot.com/2009/02/surface-at-open-space-code-day.html">Chris O&#8217;Dell</a></li>
<li><a href="http://blogs.conchango.com/jamiethomson/archive/2009/02/01/open-space-coding-using-the-ssds-rest-library.aspx">Jamie Thomson</a></li>
</ul>
<p>Photo by <a href="http://www.flickr.com/photos/alan-dean/sets/72157613146486709/">Alan Dean</a></p>
]]></content:encoded>
			<wfw:commentRss>http://gojko.net/2009/02/03/how-to-improve-testability-of-web-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Video from the Selenium talk</title>
		<link>http://gojko.net/2008/09/03/video-from-the-selenium-talk/</link>
		<comments>http://gojko.net/2008/09/03/video-from-the-selenium-talk/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 19:22:15 +0000</pubDate>
		<dc:creator>gojko</dc:creator>
				<category><![CDATA[presentations]]></category>
		<category><![CDATA[acceptance testing]]></category>
		<category><![CDATA[cubictest]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[skills matter]]></category>
		<category><![CDATA[stiq]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gojko.net/?p=330</guid>
		<description><![CDATA[Here is the video from the Testing Web Applications with Selenium and Selenium Remote Control talk that Milan Bogdanovic, Ivan Sanchez and I organised last week at Skills Matter. The first part of the talk introduces Selenium and some related tools that allow us to use Selenium easier. In the...]]></description>
			<content:encoded><![CDATA[<p><embed id="VideoPlayback" src="http://video.google.com/googleplayer.swf?docid=2555750123066853800&#038;hl=en&#038;fs=true" style="float:right; width:400px;height:326px;margin:5px 5px 5px 5px" allowFullScreen="true" allowScriptAccess="always" type="application/x-shockwave-flash"></embed> Here is the video from the <a href="http://skillsmatter.com/podcast/open-source-dot-net/testing-web-applications-with-selenium-selenium-remote-control" target="_blank">Testing Web Applications with Selenium and Selenium Remote Control</a> talk that Milan Bogdanovic, Ivan Sanchez and I organised last week at Skills Matter. The first part of the talk introduces Selenium and some related tools that allow us to use Selenium easier. In the second part, Milan demonstrates Selenium IDE and talks about Selenese language. In the third part, Ivan talks about Remote Control, how to make tests easier to manage and introduced the Page Object pattern. <a href="http://gojko.net/2008/08/28/links-and-slides-from-testing-web-applications-with-selenium/"> Download links and slides from the talk.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://gojko.net/2008/09/03/video-from-the-selenium-talk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clean your HTML inputs or the dog-eaters will get to you</title>
		<link>http://gojko.net/2008/06/23/clean-your-html-inputs-or-the-dog-eaters-will-get-to-you/</link>
		<comments>http://gojko.net/2008/06/23/clean-your-html-inputs-or-the-dog-eaters-will-get-to-you/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 16:52:27 +0000</pubDate>
		<dc:creator>gojko</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gojko.net/?p=142</guid>
		<description><![CDATA[Last month, I took a short break from my computer and went on a holiday. When I came back I was surprised to find that, while I was on the beach, Google sent quite a few people looking for underground Korean adult movies to my web log. I don&#8217;t know...]]></description>
			<content:encoded><![CDATA[<p><img src="/images/983892_dishwasher_cube_2.jpg" align="left" style="border: 1px solid black; margin:5px 5px 5px 5px" />Last month, I took a short break from my computer and went on a holiday. When I came back I was surprised to find that, while I was on the beach, Google sent quite a few people looking for underground Korean adult movies to my web log. I don&#8217;t know what is so special about the Korean illegal film industry, but considering that they also eat dogs there, it must be something very interesting to watch. I guess that you can find anything on Internet these days, but why were they looking for it on my web site? The answer to that question turned out to be another great example of why inputs should be sanitised no matter how unimportant. <span id="more-142"></span></p>
<p>I use WordPress for my blog, and so far I am relatively satisfied with it. As a very popular online software package, it does get attacked a lot and security updates are released every once in a while. My site was hacked last year and the bastards dumped a bunch of hidden porn site links in about twenty articles, which took me a few days to clear up. So I learned the hard way that when the admin console suggests an upgrade, I should take its advice. I also added a cron task to check for a few keywords in the database and alert me if someone starts advertising limb enlargement devices for free, and since then I had no real problems. That is, until my site became a hot spot for south-east Asian smut aficionados overnight. </p>
<p>My first guess was that someone was simply spamming me with fake referrer headers, since there was absolutely no reason why my web site would actually appear in Google&#8217;s search results for adult movies, Korean or with a different geographic origin. Web sites use request referrer headers to identify where the visitors are coming from. A web browser will send the address of the site where you click on a link to the linked web site, if you have not turned that off. It is not a 100% reliable mechanism to identify visitor sources, as some people turn that feature off and some browsers have bugs and send rubbish, but in general it works OK. With the recent surge in the number of blogs, a new kind of spamming started to take place online. Spammers send fake requests to web sites, putting the address of the web site they are advertising into the referrer header. The rationale behind it is, I guess, to make the site owners to click on the referrer link to see who is sending people to their web site. </p>
<p>But there were quite a few of those requests, much more than with typical spam. The visitors were led to the search web page, and did not look at any other page after that, which could be explained by the fact that they were probably disappointed to find only clips of an ugly bald guy talking about agile acceptance testing instead of their favourite underground adult stars. However, with the web page they downloaded images, css and javascript files, which spammers typically don&#8217;t do. I did not know which article actually brought the unexpected guests since only the search page was affected. The database lookup did not help either &mdash; luckily this time it seemed that the site was not hacked.</p>
<p>I tried out the query on Google, just for fun, to be absolutely amazed that my site was the third on the list. Sure enough, my search page was there. I simply had to click on that to see what happens, and a few seconds later I was looking at a spam web site. My web logs showed a hit from Google again, but I was not looking at my site. Clicking on the “cached” link on Google led to the same outcome. I grabbed the page using wget, which definitely would not jump out directly, and there I found the words “korean underground adult movies”, but only after the “There are no results for&#8230;” phrase. More interesting, after that, there was a HTML image tag with “-1.com” as the source, and an onError event redirecting people to the spam web site. When the page loaded, the browser could not find -1.com to load the picture, and fired the onError event, sending the visitors from my web site to some place they could probably watch something more to their liking. Not a bad trick at all!</p>
<p>God knows how they got Google to index my web page with both their keywords and the redirection tag as a search phrase, but they did. And it&#8217;s not only my blog, there&#8217;s a few thousand other sites with the same problem. Search on google for “onerror freeimagew” to see them.  The results containing &lt;/title&gt; in the site name will probably redirect you automatically to the spam site. </p>
<p><img src="/images/979452_clean_it_3.jpg" align="right" style="border: 1px solid black; margin:5px 5px 5px 5px" /> The problem was that my blog just dumped out whatever people put into the search form when it could not find any relevant posts. The input string was properly sanitised before it was sent to the database, and WordPress generally cleans up all user submitted comments from hostile content, but it looks like they did not think of someone using the search form to hack the web site. In any case, I just changed the theme search.php file to print “Sorry, no posts matched your criteria” when there are no results, and that fixed the problem. A proper solution would be to strip out HTML tags from the search but I was too lazy to look for all the places where the phrase could be set.</p>
<p>In any case, this is one more example how important it is to filter and sanitise everything put in by web site users, regardless of how safe it may seem, and never ever printing it back on the web site without checking for potential problems. </p>
<p>Image credits: <a href="http://www.sxc.hu/profile/lusi" target="_blank">Sonja Gjenero</a></p>
]]></content:encoded>
			<wfw:commentRss>http://gojko.net/2008/06/23/clean-your-html-inputs-or-the-dog-eaters-will-get-to-you/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Castle Demo App #4: Unit testing Monorail web sites</title>
		<link>http://gojko.net/2008/06/09/castle-demo-app-4-unit-testing-monorail-web-sites/</link>
		<comments>http://gojko.net/2008/06/09/castle-demo-app-4-unit-testing-monorail-web-sites/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 08:51:13 +0000</pubDate>
		<dc:creator>gojko</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[castle]]></category>
		<category><![CDATA[monorail]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gojko.net/?p=133</guid>
		<description><![CDATA[One of the best things about Castle Monorail MVC engine is that it allows us to test controllers from the IDE, without actually deploying anything to the web server. A major problem with most web development environments, including classic ASP.NET, is that the workflow and session logic can only be...]]></description>
			<content:encoded><![CDATA[<p>One of the best things about Castle Monorail MVC engine is that it allows us to test controllers from the IDE, without actually deploying anything to the web server. A major problem with most web development environments, including classic ASP.NET, is that the workflow and session logic can only be tested through the UI. User interface testing is slow, pain to maintain and <a href='http://gojko.net/2007/09/25/effective-user-interface-testing/'>generally does not pay off as much as code unit tests do</a>. Monorail’s programming model allows us to test workflow and session logic from the code, leaving only the actual rendering outside the reach of unit tests. That is how Monorail empowers us to really apply agile principles to web development, and saves us even more time and effort.<span id="more-133"></span></p>
<p>For those of you that have just joined this tutorial, this is the fourth iteration of the EvilLink web application, that I am building as a way to demonstrate features of the Castle Project application framework and to present some of the best practices for web application development using the Castle Project. Previous articles in this tutorials are:</p>
<ul>
<li><a href='http://gojko.net/2008/05/07/castle-demo-app-activerecord-basics-and-unit-testing/'>ActiveRecord basics and unit testing</a></li>
<li><a href='http://gojko.net/2008/05/13/castle-demo-app-2-monorail-basics/'>Monorail basics</a></li>
<li><a href='http://gojko.net/2008/05/26/castle-demo-app-3-saving-time-and-effort-with-advanced-monorail-features/'>Saving time and effort with advanced Monorail features</a></li>
</ul>
<p>So far, we have developed a skeleton of the web application that has user operations and link management functionality. Now we write some unit tests for the controllers. </p>
<p><i>A quick note before we begin. If you are in UK this week, you might want to come to the free session on <a href='http://skillsmatter.com/event/open-source-dot-net/developing-ajax-web-applications-with-castle-monorail'>developing Ajax applications with Monorail that will take place on Thursday (12/06) afternoon at Skills Matter offices in London</a>. This will give us a chance to discuss any questions about this application as well face to face.</i></p>
<h3>Isolating controllers</h3>
<p>The first thing we need to do in order to make our controllers unit testable is to isolate them from any external dependencies, including the System.Web.Http objects. Most of the code that would normally be bound to those objects is handled by Monorail anyway. The only place where System.Web objects are used directly is in the UserContext session wrapper. So let’s replace the UserContext object with an interface and a default implementation. Then we can provide a dummy or mock implementation for unit testing. </p>
<div style="padding-bottom:10pt">
<pre style="text-autospace:none;font-size:10.0pt;font-family:Courier New">
<span style='color:blue'>using</span><span> System.Web;</span>
<span style='color:blue'>using</span><span> EvilLink.Database;</span>
<span style='color:blue'>namespace</span><span style='font-size: 10.0pt;font-family:"Courier New"'> EvilLink.Controllers</span>
<span>{</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>interface</span> <span style='color:teal'>IUserContext</span> {</span>
<span>        <span style='color:blue'>int</span>? CurrentUserId { <span style='color:blue'>get</span>; <span style='color:blue'>set</span>;}</span>
<span>        <span style='color:teal'>User</span> CurrentUser { <span style='color:blue'>get</span>; }</span>
<span>    }</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>class</span> <span style='color:teal'>WebUserContext</span>:<span style='color:teal'>IUserContext</span> </span>
<span>    {</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>int</span>? CurrentUserId</span>
<span>        {</span>
<span>            <span style='color:blue'>get</span></span>
<span>            { </span>
<span>              <span style='color:blue'>return</span> System.Web.<span style='color:teal'>HttpContext</span>.Current.Session[<span style='color:maroon'>&quot;currentUserId&quot;</span>]</span>
<span>               <span style='color:blue'>as</span> <span style='color:blue'>int</span>?; </span>
<span>            }</span>
<span>            <span style='color:blue'>set</span></span>
<span>            { </span>
<span>              System.Web.<span style='color:teal'>HttpContext</span>.Current.Session[<span style='color:maroon'>&quot;currentUserId&quot;</span>] = <span style='color:blue'>value</span>;</span>
<span>            }</span>
<span>        }</span>
<span>        <span style='color:blue'>public</span> <span style='color:teal'>User</span> CurrentUser</span>
<span>        {</span>
<span>            <span style='color:blue'>get</span> { <span style='color:blue'>return</span> <span style='color:teal'>User</span>.Find(CurrentUserId); }</span>
<span>        }</span>
<span>    }</span>
<span>}</span>
</pre>
</div>
<p>Now we have to propagate this change to the controllers. Change the field type to IUserContext and create two constructors. The no-parameter constructor will automatically set the default implementation so that our application continues to work as before, but we can also set the context from the outside using the constructor with a parameter.</p>
<div style="padding-bottom:10pt">
<pre style="text-autospace:none;font-size:10.0pt;font-family:Courier New">
<span style='color:blue'>public</span><span> <span style='color:blue'>class</span> <span style='color:teal'>UserOpsController</span> : <span style='color:teal'>SmartDispatcherController</span></span>
<span>{</span>
<span>    <span style='color:blue'>private</span> <span style='color:teal'>IUserContext</span> context;        </span>
<span>    <span style='color:blue'>public</span> UserOpsController(){</span>
<span>        context=<span style='color:blue'>new</span> <span style='color:teal'>WebUserContext</span>();</span>
<span>    }</span>
<span>    <span style='color:blue'>public</span> UserOpsController(<span style='color:teal'>IUserContext</span> ctx)</span>
<span>    {</span>
<span>        context = ctx;</span>
<span>    }</span>
</pre>
</div>
<p>This is how we would mock out any external services that controllers may be connecting to or other stuff that prevents unit testing. At the moment, the controllers are still tied to the default implementation with a compile-time dependency. In the next article of this tutorial we look into better ways to handle that, using the Windsor dependency injection container.</p>
<h3>Completely detaching from the real Web</h3>
<p>Now create a new project in the solution, called EvilLink.Controllers.Test. Add references to Castle.ActiveRecord, Castle.Monorail.Framework, Castle.Monorail.TestSupport, NHibernate and nunit.framework DLLs. Also add references to EvilLink.Controllers, EvilLink.Database and EvilLink.Database.Test projects that we have developed so far. This new project will host our controller unit tests. </p>
<p>The Castle.Monorail.TestSupport library has almost all the support we need to unit test controllers. It provides us with a mock HTTP environment implementation that allows controllers to execute and be inspected in the code. Class BaseControllerTest does all the heavy lifting, we just need to subclass it and call PrepareController to initialize the controller. Then we can execute any of the controller methods directly and verify the effects on the domain or check controller properties to verify messages or objects prepared for rendering. All subclasses of SmartDispatcherController have a public Context property that allows us to inspect the Rails engine context as well. </p>
<p>There is just one slight problem with the BaseControllerTest. All its interesting methods are protected, so the test class has to subclass BaseControllerTest. It would be ideal to reuse the unit testing support for the data access layer that we developed in <a href='http://gojko.net/2008/05/07/castle-demo-app-activerecord-basics-and-unit-testing/'>the first article</a>, but C# does not support multiple inheritance. A workaround for that is to extend BaseControllerTest once, expose appropriate methods as public, and then embed that into another test class that initialises the data access system. Here is MRTestBase class that provides all the functionality of ARTestBase and also allows us to initialise controllers for testing:</p>
<div style="padding-bottom:10pt">
<pre style="text-autospace:none;font-size:10.0pt;font-family:Courier New">
<span style='color:blue'>using</span><span> EvilLink.Database.Test;</span>
<span style='color:blue'>using</span><span> Castle.MonoRail.TestSupport;</span>
<span style='color:blue'>using</span><span> Castle.MonoRail.Framework;</span>
<span style='color:blue'>namespace</span><span style='font-size: 10.0pt;font-family:"Courier New"'> EvilLink.Controllers.Test</span>
<span>{</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>class</span> <span style='color:teal'>ConcreteControllerTest</span>:<span style='color:teal'>BaseControllerTest</span>{</span>
<span>        <span style='color:green'>// just expose PrepareController as a public method</span></span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>void</span> InitController(<span style='color:teal'>Controller</span> controller)</span>
<span>          {           </span>
<span>            PrepareController(controller);</span>
<span>          }</span>
<span>    }</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>class</span> <span style='color:teal'>MRTestBase</span>:<span style='color:teal'>ARTestBase</span></span>
<span>    {</span>
<span>        <span style='color:blue'>private</span> <span style='color:teal'>ConcreteControllerTest</span> context = <span style='color:blue'>new</span> <span style='color:teal'>ConcreteControllerTest</span>();</span>
<span>        <span style='color:green'>// expose InitController</span></span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>void</span> InitController(<span style='color:teal'>Controller</span> controller)</span>
<span>        {</span>
<span>            context.InitController(controller);</span>
<span>        }</span>
<span>    }</span>
<span>}</span>
</pre>
</div>
<p>We can use a dummy implementation of the user context, not tied to the real HttpSession object, to verify the session storage (this would be a good place to use a mock factory).</p>
<div style="padding-bottom:10pt">
<pre style="text-autospace:none;font-size:10.0pt;font-family:Courier New">
<span style='color:blue'>using</span><span> EvilLink.Database;</span>
<span style='color:blue'>namespace</span><span style='font-size: 10.0pt;font-family:"Courier New"'> EvilLink.Controllers.Test</span>
<span>{</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>class</span> <span style='color:teal'>DummyUserContext</span>:<span style='color:teal'>IUserContext</span></span>
<span>    {</span>
<span>        <span style='color:blue'>private</span> <span style='color:blue'>int</span>? currentuserid;</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>int</span>? CurrentUserId</span>
<span>        {</span>
<span>            <span style='color:blue'>get</span> { <span style='color:blue'>return</span> currentuserid; }</span>
<span>            <span style='color:blue'>set</span> { currentuserid = <span style='color:blue'>value</span>; }</span>
<span>        }</span>
<span>        <span style='color:blue'>public</span> <span style='color:teal'>User</span> CurrentUser</span>
<span>        {</span>
<span>            <span style='color:blue'>get</span> { <span style='color:blue'>return</span> currentuserid == <span style='color:blue'>null</span> ? </span>
<span>                <span style='color:blue'>null</span> : <span style='color:teal'>User</span>.Find(currentuserid); }</span>
<span>        }</span>
<span>    }</span>
<span>}</span>
</pre>
</div>
<h3>Writing NUnit tests</h3>
<p>We can now write a couple of unit tests inspecting the workflow and session behaviour of the user operations controller. In the setup, we initialise context objects, create a user to play with and prepare the controller. Notice that we just call the constructor and then pass the object to PrepareController and that is it &mdash; no black magic involved. We can call the login method and then inspect the user context to check whether the expected user object was stored in the session. We can also try to log in with an incorrect password and verify the message coming out (hint: PropertyBag is a public property of the controller, so we can inspect it directly). The SelectedViewName property will give us a way to check which view was selected for rendering. We can verify that the controller initiated redirection by checking Context.Response.WasRedirected property, but I don’t know of a good way to verify redirection URL at the moment. Jimmy Bogard <a href='http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/02/18/unit-testing-monorail-controllers-redirects.aspx'>explored some options for that like changing the redirect method</a>. Apart from that, we can easily test everything else:</p>
<div style="padding-bottom:10pt">
<pre style="text-autospace:none;font-size:10.0pt;font-family:Courier New">
<span style='color:blue'>using</span><span> EvilLink.Database.Test;</span>
<span style='color:blue'>using</span><span> NUnit.Framework;</span>
<span style='color:blue'>using</span><span> EvilLink.Database;</span>
<span style='color:blue'>using</span><span> Castle.MonoRail.TestSupport;</span>
<span>&nbsp;</span>
<span style='color:blue'>namespace</span><span style='font-size: 10.0pt;font-family:"Courier New"'> EvilLink.Controllers.Test</span>
<span>{</span>
<span>    [<span style='color:teal'>TestFixture</span>]</span>
<span>    <span style='color:blue'>public</span> <span style='color:blue'>class</span> <span style='color:teal'>TestUserOps</span>:<span style='color:teal'>MRTestBase</span></span>
<span>    {</span>
<span>        <span style='color:teal'>DummyUserContext</span> wuc;</span>
<span>        <span style='color:teal'>UserOpsController</span> ops;</span>
<span>        <span style='color:teal'>User</span>  mike;</span>
<span>        [<span style='color:teal'>SetUp</span>]</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>override</span> <span style='color:blue'>void</span> SetUp()</span>
<span>        {</span>
<span>            <span style='color:blue'>base</span>.SetUp();</span>
<span>            wuc = <span style='color:blue'>new</span> <span style='color:teal'>DummyUserContext</span>();</span>
<span>            ops = <span style='color:blue'>new</span> <span style='color:teal'>UserOpsController</span>(wuc);</span>
<span>            InitController(ops);            </span>
<span>            mike = <span style='color:blue'>new</span> <span style='color:teal'>User</span>(<span style='color:maroon'>&quot;mike&quot;</span>, <span style='color:maroon'>&quot;mike&quot;</span>, <span style='color:maroon'>&quot;mpass&quot;</span>, <span style='color:maroon'>&quot;m@m.com&quot;</span>);</span>
<span>            mike.SaveAndFlush();</span>
<span>        }</span>
<span>        [Test]</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>void</span> TestLogin()</span>
<span>        {</span>
<span>            ops.Login(<span style='color:maroon'>&quot;mike&quot;</span>, <span style='color:maroon'>&quot;mpass&quot;</span>, <span style='color:maroon'>&quot;/home&quot;</span>);          </span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(mike, wuc.CurrentUser);           </span>
<span>        }</span>
<span>        [Test]</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>void</span> TestLoginIncorrectPassword()</span>
<span>        {</span>
<span>            ops.Login(<span style='color:maroon'>&quot;mike&quot;</span>, <span style='color:maroon'>&quot;wrongpass&quot;</span>, <span style='color:maroon'>&quot;/home&quot;</span>);</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:blue'>null</span>, wuc.CurrentUser);           </span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:maroon'>&quot;Username or password incorrect, please try again&quot;</span>,</span>
<span>                   ops.PropertyBag[<span style='color:maroon'>&quot;error&quot;</span>]);</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(ops.Name+<span style='color:maroon'>&quot;\\index&quot;</span>, ops.SelectedViewName);</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:maroon'>&quot;/home&quot;</span>, ops.PropertyBag[<span style='color:maroon'>&quot;goBackUrl&quot;</span>]);            </span>
<span>        }</span>
<span>        [Test]</span>
<span>        <span style='color:blue'>public</span> <span style='color:blue'>void</span> TestRegisterUser()</span>
<span>        {</span>
<span>            ops.SubmitRegistration(</span>
<span>              <span style='color:blue'>new</span> <span style='color:teal'>User</span>(<span style='color:maroon'>&quot;tom&quot;</span>, <span style='color:maroon'>&quot;tsmith&quot;</span>, <span style='color:maroon'>&quot;tpass&quot;</span>, <span style='color:maroon'>&quot;t@t.com&quot;</span>));</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(</span>
<span>             <span style='color:maroon'>&quot;You have registered successfully. You can now log in.&quot;</span>,</span>
<span>                ops.Context.Flash[<span style='color:maroon'>&quot;message&quot;</span>]);</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:blue'>true</span>, ops.Context.Response.WasRedirected);</span>
<span>            <span style='color:teal'>User</span> u=<span style='color:teal'>User</span>.FindAllByProperty(<span style='color:maroon'>&quot;Username&quot;</span>, <span style='color:maroon'>&quot;tsmith&quot;</span>)[0];</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:maroon'>&quot;tom&quot;</span>, u.Name);</span>
<span>            <span style='color:teal'>Assert</span>.AreEqual(<span style='color:maroon'>&quot;t@t.com&quot;</span>, u.Email);</span>
<span>        }</span>
<span>    }</span>
<span>}</span>
</pre>
</div>
<p>Build the project, fire up your NUnit test runner, and you should see the tests pass:</p>
<p><img src='/images/nunit-ctrl-small.png'/></p>
<h3>Some links for the end</h3>
<ul>
<li><a href='/resources/EvilLink_i4.zip'>Source code for this iteration</a></li>
<li><a href='http://using.castleproject.org/display/MR/TDDingControllers' target='_blank'>More detailed information about BaseControllerTest</a></li>
<li><a href='http://castleproject.org/monorail/documentation/v1rc2/usersguide/testing.html' target='_blank'>Older library for testing, that works by simulating complete http requests and responses. </a></li>
</ul>
<h3>Stuff to remember</h3>
<ul>
<li>BaseControllerTest class from Castle.Monorail.TestSupport provides a framework to unit test controllers.</li>
<li>Just create the controller as any other object and pass it to the PrepareController method of BaseControllerTest to be able to call its methods directly</li>
<li>SmartDispatcherController exposes almost everything interesting to verify as public properties, including SelectedView, PropertyBag and Context.</li>
</ul>
<h3>Next exercise</h3>
<p>In the next article of this tutorial, we look into injecting services and configuration into controllers using the Windsor dependency injection framework. That article should be online soon. (Subscribe to <a href='http://gojko.net/feed/'>RSS updates</a> to get notified about that). As I mentioned above, if you are in UK, come to the free session on <a href='http://skillsmatter.com/event/open-source-dot-net/developing-ajax-web-applications-with-castle-monorail'>developing Ajax applications with Monorail that will take place on Thursday 12th</a> to learn more about what Castle can do for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://gojko.net/2008/06/09/castle-demo-app-4-unit-testing-monorail-web-sites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

