Home

Castle Stronghold

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

  1. Create a Class Library project (usually you are going to use the same solution of the web project)
  2. Add references to :
    • nunit.framework
    • Castle.MonoRail.Framework
    • Castle.MonoRail.TestSupport
  3. Create test cases class extending AbstractMRTestCase
  4. 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)
  5. 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.
Quick Note

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.

Google
Search WWW Search castleproject.org