views:

145

answers:

4

hello, i'm building some basic crud methods for my fluently mapped entities.

i just wanna know if there is a simple way to make the transaction to perform a rollback when i'm running the cud test methods ?

the code that being tested perform the commit inside

here is a create sample:

 public int? Create(IIdentifiable entity)
    {
        int? newId = null;
        using (ISession session = SessionFactoryProvider.NewSession)
        using (ITransaction transaction = session.BeginTransaction())
        {
            object newObj = session.Save(entity);
            newId = (int?)newObj;
            transaction.Commit();
        }

        return (int?)newId;
    }
A: 

Hmm, I don't think that it is a good idea to let your method create a session and perform transaction handling .... Unless that method is also a service boundary.

Suppose you want to create multiple entities in one and the same transaction, how are you going to handle that ?

Frederik Gheysels
its a service boundary, no multy entity creation
Chen Kinnrot
+1  A: 

Check FUBUMVC Contrib for a great NHibernate CRUD testing method.

mxmissile
+2  A: 

If you're using xUnit.net, there's an AutoRollback attribute in the contrib project. If you're open to using System.Transactions then you can create a new transaction before the session.Open() and session should autoenlist (unless you've set ado.net to not autoenlist). Then just abandon at the end.

I did something similar to this a (long) while ago:

public class TransactionalTest
{
 public TransactionalTest()
 {
  Transaction.Current = new CommittableTransaction();
 }

 ~TransactionalTest()
 {
  if (Transaction.Current != null &&
   Transaction.Current.TransactionInformation.Status !=
   TransactionStatus.Committed)
  {
   Transaction.Current.Rollback();
  }
 }
}

Then just have your test extend TransactionalTest. But, I think NUnit, MbUnit and xUnit.net all support transactional tests out of the box or with a contrib project.

Ben
A: 

For integration testing, I use a session decorator to auto commit and evict the entity. You could adapt it for your situation:

public class AutoCommitAndEvictSession : SessionDecorator {

    public AutoCommitAndEvictSession(ISession session)
        : base(session) { }

    public override object Save(object obj) {
        object result;
        using (var tx = Session.BeginTransaction()) {
            result = Session.Save(obj);
            tx.Commit();
        }
        Session.Evict(obj);
        return result;
    }

    public override void Update(object obj) {
        CommitAndEvict(base.Update, obj);
    }

    public override void Delete(object obj) {
        CommitAndEvict(base.Delete, obj);
    }

    private void CommitAndEvict(Action<object> action, object entity) {
        using (var tx = Session.BeginTransaction()) {
            action.Invoke(entity);
            tx.Commit();
        }
        Session.Evict(entity);
    }
}

You can find more details on usage with examples here: http://www.agileatwork.com/integration-testing-with-nhibernate/

Michael Valenty