Testing with NHibernate and SQLite

warninglabel

There does not seem to be too much details on how to set up a test environment for NHibernate testing using SQLite. Ayende has a nice post on this, but he does not go into details of how, what and where, so I decided to fill in the blanks, and provide an up to date sample for NHibernate 2.1.

Let’s first gather all the things we need:

Now we need to add references to all these projects. Make sure you add correct reference to System.Data.SQLite (either x86 version from the main directory, or x64 version from x64 folder if you’re running on 64bits).

You also can’t add reference to sqlite3.dll, because it’s an unmanaged dll. I simply add it as element to solution and set it to copy to output directory. After all, your solution should look roughly like this:

NHibernate_tests

I also have a base class for my tests that does all the setup for me. Here’s how it looks like:

[TestFixture]
public abstract class DbTestsBase<T>
{
    protected ISessionFactory factory;
    protected T sut;
 
    private string dbFile;
 
    public void Init(params Assembly[] assembliesWithMappings)
    {
        dbFile = GetDbFileName();
        EnsureDbFileNotExists();
 
        NHibernateProfiler.Initialize();
        var configuration = new Configuration()
            .AddProperties(new Dictionary<string, string>
                               {
                                   { Environment.ConnectionDriver, typeof( SQLite20Driver ).FullName },
                                   { Environment.Dialect, typeof( SQLiteDialect ).FullName },
                                   { Environment.ConnectionProvider, typeof( DriverConnectionProvider ).FullName },
                                   { Environment.ConnectionString, string.Format( "Data Source={0};Version=3;New=True;", dbFile) },
                                   { Environment.ProxyFactoryFactoryClass, typeof( ProxyFactoryFactory ).AssemblyQualifiedName },
                                   { Environment.Hbm2ddlAuto, "create" },
                                   { Environment.ShowSql, true.ToString() }
                               });
        foreach (var assembly in assembliesWithMappings)
        {
            configuration.AddAssembly(assembly);
        }
 
        new Remapper().Remap(configuration);
 
        factory = configuration.BuildSessionFactory();
    }
 
    [TearDown]
    public void TearDownTests()
    {
        factory.Dispose();
        EnsureDbFileNotExists();
        NHibernateProfiler.Stop();
    }
 
    private string GetDbFileName()
    {
        var path = Path.GetFullPath(Path.GetRandomFileName() + ".Test.db");
        if (!File.Exists(path))
        {
            return path;
        }
 
        // let's try again
        return GetDbFileName();
    }
 
    private void EnsureDbFileNotExists()
    {
        if (File.Exists(dbFile))
        {
            File.Delete(dbFile);
        }
    }
}

There are couple interesting points in this code:

I expose the SessionFactory, not Session. That’s because I use this class for testing repositories in stateful application, that manage the session themselves.

I save the database to file, instead of keeping it in memory like Ayende does. That’s connected to the previous fact. Apparently, in-memory database only lives as long as session that created it, which does not cut it for me.

I then use the class like this:

[TestFixture]
class Entity1Tests : DbTestsBase<Entity1>
{
    [SetUp]
    public void SetUp()
    {
        base.Init(typeof(Entity1).Assembly);
    }
 
    [Test]
    public void Member_should_action()
    {
        //some code
    }
}

Pretty simple and so far, covers my needs.

Technorati Tags: ,,

Comments

Eddie Cianci says:

Nice post! (And thanks for the Dynamic Proxy series, I wish we had similar series for other parts of the Castle stack, like Windsor)

I use a similar superclass for my integration tests, but I lean heavily on some of the support classes in FluentNHibernate:

1) SingleConnectionSessionSourceForSQLiteInMemoryTesting()
2) fluent Database Configuration using SQLiteConfiguration.Standard

Here’s a link to a copy of the whole thing, it’s only about 15-20 lines: http://gist.github.com/166781

@Eddie,

very cool – I had no idea this existed in FNH. I’ve got to take it to a spin when it’s released.

As for Windsor tutorial, BitterCoder has a nice one: wiki.bittercoder.com/…/Default.aspx

But also, Windsor has a pretty descent documentation, whereas for DP there’s no docs whatsoever at the moment.