Unit testing
MonoRail uses the ASP.Net infrastructure to run a web site and run tests against it. Originally the idea was to supply a custom web.config so the web site would run with a different configuration (like testing database).
Unfortunatelly the ASP.Net infrastructure does not permit this overriding, so testing can be somewhat limited, or force you to handle this creatively. For example, in a build process set up a testing site infrastructure and run the test against it.
Castle.MonoRail.TestSupport
Castle.MonoRail.TestSupport was created to enable easy testing of MonoRail projects. It uses the ASP.Net runtime to create mock requests and asserts the response. It also exposes the PropertyBag, Flash and Session dictionaries so you can write assert for their contents as well.
In order to use the ASP.Net runtime, the assembly Castle.MonoRail.TestSupport.dll must be registered in the GAC. If you have installed Castle using the MSI distribution this was already done for you. Otherwise, execute:
> gacutil /i Castle.MonoRail.TestSupport
Simple recipe
- Create a Class Library project (usually you are going to use the same solution of the web project)
-
Add references to :
- nunit.framework
- Castle.MonoRail.Framework
- Castle.MonoRail.TestSupport
- Create test cases class extending AbstractMRTestCase
-
Now expose the web application folder to the AbstractMRTestCase, you can do it in two ways:
- Create a configuration file to associate with the AppDomain, or
- Simply override the method GetPhysicalDir (more about that later)
- Finally use the Assert family of methods exposed by AbstractMRTestCase
A simple example from MonoRail test case
The following class is a snippet of one of the MonoRail test cases:
[TestFixture] public class BasicFunctionalityTestCase : AbstractMRTestCase { [Test] public void SimpleControllerAction() { DoGet("home/index.rails"); AssertSuccess(); AssertReplyEqualsTo( "My View contents for Home\\Index" ); } [Test] public void Flash() { DoGet("home/flash1.rails"); AssertSuccess(); AssertFlashEntryEquals("errormessage", "Some error"); } [Test] public void Redirect() { DoGet("home/redirectAction.rails"); AssertSuccess(); AssertRedirectedTo( "/home/index.rails" ); } [Test] public void PropertyBag() { DoGet("home/bag.rails"); AssertSuccess(); AssertPropertyBagContains( "CustomerName" ); AssertPropertyBagEntryEquals( "CustomerName", "hammett" ); AssertReplyEqualsTo( "\r\nCustomer is hammett\r\n\r\n123" ); } [Test] public void CreateCookie() { DoGet("cookies/addcookie.rails"); AssertSuccess(); AssertReplyEqualsTo( @"My View contents for Cookies\Index" ); Assert.AreEqual( 2, Response.Cookies.Count ); AssertHasCookie( "cookiename" ); AssertHasCookie( "cookiename2" ); AssertCookieValueEqualsTo( "cookiename", "value" ); AssertCookieValueEqualsTo( "cookiename2", "value2" ); } [Test] public void CreateCookieExpiration() { DoGet("cookies/AddCookieExpiration.rails"); AssertSuccess(); AssertReplyEqualsTo(@"My View contents for Cookies\Index"); DateTime twoWeeks = DateTime.Now.Add(new TimeSpan(14, 0, 0, 0)); AssertCookieExpirationEqualsTo("cookiename2", twoWeeks); AssertCookieValueEqualsTo("cookiename2", "value"); } }
For a complete documentation of supported asserts, check the API documentation for AbstractMRTestCase.
Exposing the web site application directory
As we use the ASP.Net runtime to run the web application, we must know the full absolute path for the web application. In the case you are confused, web application is the one with the web.config and global.asax, not the bin directory.
Overriding GetPhysicalDir
When overriding the GetPhysicalDir you must return the path to the web application:
[TestFixture] public class AccountControllerTestCase : AbstractMRTestCase { ... protected override String GetPhysicalDir() { return "../mywebapp"; } }
If you return a relative path, it is going to be converted based on the executing directory, i.e. the AppDomain.ApplicationBase.
External configuration
Another option is to create a configuration file to your test case project. The content might be something like the following:
<?xml version="1.0" encoding="utf-8" ?> <!-- App.config --> <configuration> <appSettings> <add key="web.physical.dir" value="..\TestSite" /> <add key="web.virtual.dir" value="/" /> </appSettings> </configuration>You should not need to override the virtual directory setting in most circumstances.
Visual Studio 2003/2005 hint
Create an App.config file and a Post Build Event to put the file in the right
folder:
Post build event command line:
copy $(ProjectDir)\App.config $(TargetPath).config
AbstractMRTestCase Quick Reference
For a complete documentation of supported asserts, check the API documentation for AbstractMRTestCase.