Testing CRUD Operations With NHibernate
Posted by Davy Brion on December 7th, 2009
I was asked to show how you can easily do CRUD tests, so here’s a base class that makes it very easy
public abstract class CrudTest<TEntity, TId> : NHibernateTest
where TEntity : IHaveAnId<TId>
{
[Test]
public virtual void SelectQueryWorks()
{
session.CreateCriteria(typeof(TEntity)).SetMaxResults(5).List();
}
[Test]
public virtual void AddEntity_EntityWasAdded()
{
var entity = BuildEntity();
InsertEntity(entity);
session.Evict(entity);
var reloadedEntity = session.Get<TEntity>(entity.Id);
Assert.IsNotNull(reloadedEntity);
AssertAreEqual(entity, reloadedEntity);
AssertValidId(reloadedEntity);
}
[Test]
public virtual void UpdateEntity_EntityWasUpdated()
{
var entity = BuildEntity();
InsertEntity(entity);
ModifyEntity(entity);
UpdateEntity(entity);
session.Evict(entity);
var reloadedEntity = session.Get<TEntity>(entity.Id);
Assert.IsNotNull(reloadedEntity);
AssertAreEqual(entity, reloadedEntity);
}
[Test]
public virtual void DeleteEntity_EntityWasDeleted()
{
var entity = BuildEntity();
InsertEntity(entity);
DeleteEntity(entity);
Assert.IsNull(session.Get<TEntity>(entity.Id));
}
protected virtual void InsertEntity(TEntity entity)
{
session.Save(entity);
session.Flush();
}
protected virtual void UpdateEntity(TEntity entity)
{
session.Update(entity);
session.Flush();
}
protected virtual void DeleteEntity(TEntity entity)
{
session.Delete(entity);
session.Flush();
}
protected abstract TEntity BuildEntity();
protected abstract void ModifyEntity(TEntity entity);
protected abstract void AssertAreEqual(TEntity expectedEntity, TEntity actualEntity);
protected abstract void AssertValidId(TEntity entity);
}
Simply inherit from this class, implement the BuildEntity, ModifyEntity, AssertAreEqual and AssertValidId methods and that’s it. Those methods are usually pretty simple. In BuildEntity you just create an unpersisted entity and assign values to the properties, in ModifyEntity you modify the properties, and in AssertAreEqual you compare the properties of both instances. In AssertValidId, you make sure that the ID value is ok (depending on your identifier strategy).
This is good for regular CRUD operations, though we typically add extra tests when we want to test cascades or one-to-many associations mapped with inverse=”true”.
December 8th, 2009 at 12:52 am
Just came from your previous post. This is a nice follow-up, another worthy of bookmarking!
Supposing that you follow the multi-layer approach to your project, this code would be used in testing persistence with NHibernate, right? So higher-level code which would normally interact with NH-backed repositories would actually interact with fake version of such, just so you can keep the different test types separate…Am I right??
December 8th, 2009 at 7:09 am
@Grant
the class shown in this post is only useful to test the correctness of your mappings by making sure that CRUD operations work for all entities. and as mentioned in the previous post, we also write tests for each specific custom query that we write.
our higher level code (the one that indees communicates with repositories for all NH-related tasks) is always tested with mocked repositories.
December 8th, 2009 at 9:41 am
[...] Testing CRUD Operations With NHibernate – Davy Brion shares a simple base class which provides the groundwork for testing Create Read Update and Delete functionality of NHibernate types [...]
January 15th, 2010 at 12:03 pm
[...] by kilfour on January 15, 2010 A while ago davy brion posted a nice base class for nhbirnate crud tests, which i eagerly [...]