Home > .NET, NHibernate, TDD > Testing your NHibernate data access code using SQLite

Testing your NHibernate data access code using SQLite

November 25th, 2008 Leave a comment Go to comments

Ever since I started working professionally at a software company (which is roughly 3 years ago) I’ve been doing unit testing. I really consider automatic testing one of the most (if not THE most) important trends of software development the last decade.

But, despite that, I’ve let code close to the data access be left untested. This has been due to the pain I thought it would be to create and maintain those tests. And also I’ve thought that those tests would be way to slow to have among my other unit tests (which we want to be fast, so that we run them often).

For the first two years of my career this was not a big problem. We rarely had bugs in our data access code as it mostly consisted of simple, straight forward code. So I hadn’t really given it much thought. Until lately that is.

Then we started to get performance issues as we got some really large organizations to use or software. To resolve the performance issues we made our data access smarter so it could make more efficient queries to the database. As smarter often means more code, or at least added complexity, I saw the need of automatic tests to guarantee the quality of the code.

So, I read some articles on using SQLite with NHibernate. After some pain setting it all up, I accomplished my goal of easy data access testing. So say that I want to test GetCustomerByName in the following class (in real life I wouldn’t test methods that are this simple, but it’s just to show the idea):

public class CustomerDao

{

    private readonly INHibernateManager _sessionManager;

 

    public CustomerDao(INHibernateManager sessionManager)

    {

        _sessionManager = sessionManager;

    }

 

    public Customer GetCustomerByName(string name)

    {

        var session = _sessionManager.CurrentSession;

 

        return session.CreateQuery("from Customer where Name = :name")

            .SetParameter("name", name)

            .UniqueResult<Customer>();

    }

}

Then I can write a test like this:

public class CustomerDaoTest : BaseTest

{

    [Test]

    public void CanGetCustomerByName()

    {

        Database.Init();

        var customerA = new Customer { Name = "A" };

        var customerB = new Customer { Name = "B" };             

        Database.Save(customerA, customerB);       

        var customerDao = new CustomerDao(Database);

 

        var result = customerDao.GetCustomerByName("B");

 

        Assert.That(result, Is.EqualTo(customerB));

    }

}

For this to work I have a class called TestDatabase with the following code:

public class TestDatabase : INHibernateManager

{

    private static ISessionFactory m_sessionFactory;       

    private static SchemaExport SchemaExport;

    private ISession m_session;

 

    public void Init()

    {

        if (m_sessionFactory == null)

        {

            Configuration config = CreateNHibernateConfig();

 

            m_sessionFactory = config.BuildSessionFactory();

 

            SchemaExport = new SchemaExport(config);

        }

        if (m_session != null)

        {

            m_session.Close();

        }

        m_session = m_sessionFactory.OpenSession();

        m_session.BeginTransaction();

 

        var connection = m_session.Connection;

        SchemaExport.Execute(false, true, false, false, connection, null);

    }

 

    private static Configuration CreateNHibernateConfig()

    {

        Configuration config = new Configuration();

        config.Properties.Clear();

 

        config.SetProperty("hibernate.connection.driver_class",

            "NHibernate.Driver.SQLite20Driver");

        config.SetProperty("hibernate.dialect", "NHibernate.Dialect.SQLiteDialect");

        config.SetProperty("hibernate.connection.connection_string",

            "Data Source=:memory:;Version=3;New=True;");

        config.SetProperty("hibernate.cache.use_second_level_cache", "false");

        config.SetProperty("hibernate.hbm2ddl.auto", "create");

 

        config.AddAssembly("MyAssembly"); // Change this to your assembly

 

        return config;

    }

 

    public ISession Session

    {

        get { return m_session; }

    }

 

    public void Save(params object[] entities)

    {

        foreach (var entity in entities)

        {

            Session.Save(entity);

        }

        Session.Flush();

    }

 

    ISession INHibernateManager.CurrentSession

    {

        get { return m_session; }

    }

}

And I’ve also added the following field to my BaseTest class:

[TestFixture]

public class BaseTest

{

    protected readonly TestDatabase Database = new TestDatabase();

 

    // More code here...

}

So, in summary, I’ve shown a pretty easy way of doing database testing. Even though the method under test was really simple in the example, the same technique could be used for much more complex scenarios.

Categories: .NET, NHibernate, TDD Tags:
  1. No comments yet.
  1. No trackbacks yet.