Dashboard > ActiveRecord > ... > How to > Approaches to unit testing
Approaches to unit testing
Added by Daniel Rothmaler, last edited by Daniel Rothmaler on Aug 20, 2007
Labels: 
(None)


Testing plays the most important role on software development. With ActiveRecord we usually keep a separated database for unit testing, so all data can be deleted mercilessly.

We suggest that you use a base class for testing your object model. This greatly simplifies the task. However you have a few decisions to make:

  • Do you want to manage the schema yourself?
  • Do you want to let ActiveRecord/NHibernate create the schema for you on the test database?

If you want to manage the schema yourself, you must delete all data befor executing each test, something like the following will be enough:

protected virtual void PrepareSchema()
{
    // Remember to do it in a descendent dependency order

    Office.DeleteAll();
    User.DeleteAll();
}

Note that you have to implement the DeleteAll method on your classes. Something like

public static void DeleteAll()
{
    ActiveRecordBase.DeleteAll( typeof(Office) );
}

On the other hand, if you want to let ActiveRecord create the schema, use the following

protected virtual void PrepareSchema()
{
    ActiveRecordStarter.CreateSchema();
}

protected virtual void DropSchema()
{
    ActiveRecordStarter.DropSchema();
}

The code below is a suggestion of an abstract class to simplify unit testing:

using NUnit.Framework;

using Castle.ActiveRecord;

public abstract class AbstractModelTestCase
{
    protected SessionScope scope;

    [TestFixtureSetUp]
    public virtual void FixtureInit()
    {
        InitFramework();
    }

    [SetUp]
    public virtual void Init()
    {
        PrepareSchema();

        CreateScope();
    }

    [TearDown]
    public virtual void Terminate()
    {
        DisposeScope();

        DropSchema();
    }

    [TestFixtureTearDown]
    public virtual void TerminateAll()
    {
    }

    protected void FlushAndRecreateScope()
    {
        DisposeScope();
        CreateScope();
    }

    protected void CreateScope()
    {
        scope = new SessionScope();
    }

    protected void DisposeScope()
    {
        scope.Dispose();
    }

    protected virtual void PrepareSchema()
    {
        // If you want to delete everything from the model.
        // Remember to do it in a descendent dependency order

        // Office.DeleteAll();
        // User.DeleteAll();

        // Another approach is to always recreate the schema 
        // (please use a separate test database if you want to do that)

        ActiveRecordStarter.CreateSchema();
    }

    protected virtual void DropSchema()
    {
        ActiveRecordStarter.DropSchema();
    }

    protected virtual void InitFramework()
    {
        IConfigurationSource source = ConfigurationSettings.GetConfig("activerecord") as IConfigurationSource;

        ActiveRecordStarter.Initialize( source );

        // Remember to add the types, for example
        // ActiveRecordStarter.Initialize( source, typeof(Blog), typeof(Post) );
    }
}

A test case using this base class would be similar to

using NUnit.Framework;

[TestFixture]
public class OfficeTestCase : AbstractModelTestCase
{
    [Test]
    public void Creation()
    {
        Office myoffice = new Office("The Office");
        myoffice.Save();

        FlushAndRecreateScope(); // Persist the changes as we're using scopes

        Office[] offices = Office.FindAll();
        Assert.AreEqual( 1, offices.Length );
        Assert.AreEqual( "The Office", offices[0].Name );
    }
}

See also

Site running on a free Atlassian Confluence Community License granted to Castle Project. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.4 Build:#809 Jun 12, 2007) - Bug/feature request - Contact Administrators