Karl Cassar
Karl Cassar

Reputation: 6473

unit testing a database query via nhibernate

I need to create a unit test for a method which loads data from the database. I was researching a bit into unit testing and databases, and most articles tell you that you should mock the database. However, this method basically loads objects from a database, and performs some restrictions via SQL.

Therefore, what I want to test is that the actual database query is working successful, hence I don't think one can mock the database.

I am using NHibernate as my ORM, and the query is being built using QueryOver. I find it extremely problematic to unit-test databases, due to the database being in an inconsistent state. Any ideas / methods how one would go about doing such a test?

This is the particular method I would like to unit-test:

public IEnumerable<IArticlePanel> LoadPanelsApplicableToArticle(ArticleModule.IArticle article, Enums.ARTICLE_PANEL_LOCATION location)
   {
       CS.General_v3.Util.ContractsUtil.RequiresNotNullable(article, "Article must not be null");

       var articleList = Modules.Factories.ArticleFactory.GetAllParentsForAnArticle(article).ToList();
       articleList.Add(article);

       var q = GetQuery();
       q = q.WhereRestrictionOn(x => x.Article).IsInG(articleList.ConvertAll<long>(x => ((IBaseDbObject)x).ID));
       q = q.Where(x => x.Location == location);
       return FindAll(q);
 }

Upvotes: 3

Views: 2225

Answers (3)

znelson
znelson

Reputation: 924

We use IRepository from NCommon. Then we use InMemoryRepository for unit testing. Very slick, fast, and easy to use.

Upvotes: 0

Cole W
Cole W

Reputation: 15303

Personally I have used real databases to do my integration tests. I feel that this is the closest to real production scenarios as possible. Our development team is not currently generating the database from the nhibernate mappings so there were some inconsistencies between the mappings and the database (things like database defaults etc). If you are generating the schema from nhibernate SQLLite may be the right path for you. But if you aren't I personally feel that it's better to write these tests against the real database.

My integration tests will insert the necessary data for the tests and delete the data after the test. The only pitfall to this method is that you have to make sure you delete all the data after your test is over otherwise it could affect other tests. I've found this to be a viable solution for our company though and it's been extremely helpful. We have a dedicated database only used for unit testing.

Below is an example of one of my tests:

[TestMethod]
public void Test_NHibernate_Query()
{
    //Create the data in the database necessary to test my nhibernate query
    CreateDataForUnitTest();

    IInventoryRepository target = new InventoryRepository(nhibernateSession);

    IList<InventoryView> inventoryRecords = target.GetContainerInventory(productId);

    Assert.AreEqual(1, inventoryRecords.Count);
}

[TestCleanup]
public void CleanUp()
{
    DeleteAll<Order>();
    DeleteAll<Company>();
}

public void DeleteAll<T>() where T : Entity
{
    NHibernate.ISession session = SessionFactory.GetCurrentSession();

    using (NHibernate.ITransaction tran = session.BeginTransaction())
    {
        IList<T> items = session.CreateCriteria<T>()
            .List<T>();

        foreach (T p in items)
        {
            session.Delete(p);
        }

        tran.Commit();
    }
}

Upvotes: 0

Tim Copenhaver
Tim Copenhaver

Reputation: 3302

In the past, when I've needed to unit test a database, I have usually used SQLite. You basically set up the SQLite database in memory, then configure your NHibernate (dependency injection, or however you want to do it) to connect to SQLite instead of your normal database. Almost all queries should be able to run correctly.

If you need strong DateTime support, SQLite will probably let you down (see Ayende's post about that here). In that case, you can use any of the embedded databases. I would recommend setting up a RAMDisk and place the embedded database on that disk, so it still runs in-memory.

Upvotes: 4

Related Questions