views:

779

answers:

4

I'm learning some Fluent NHibernate and I've run across the semi-awesome PersistenceSpecification class.

I've set it up in a unit test to verify my mappings and it works great. However, it leaves the record in the database when done. I tried throwing it in a transaction so I can rollback the changes but I get an error:

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'AdoTransaction'..

Without a transaction I have to figure out the ID's of the record, retrieve them and delete them and that doesn't seem very elegant.

Any thoughts?

EDIT:

Here is the code snippet:

            var factory = GetSessionFactory();
            using (var session = factory.OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                new PersistenceSpecification<TimePeriod>(session)
                        .CheckProperty(x => x.EndDate, DateTime.Today)
                        .VerifyTheMappings();
                transaction.Rollback();
            }
+1  A: 

The PersistenceSpecification is usually used with an in-memory database like SQLite, that's why it doesn't roll anything back. I believe there's a constructor overload that takes an ISession instance, have you tried getting a transaction from there then rolling that back after?

James Gregory
Yup, I created my own ISession object from a SessionFactory.OpenSession() call. From there I began a transaction and then after the VerifyTheMappings() call I tried to rollback the transaction and got an error. I'll post the full code snippet below.
MBonig
+2  A: 

I think the issue here is VerifyTheMappings() calls TransactionSave() which does a tx.Commit() to the database. As James indicated, this technique seems to work great for throw away in-memory testing techniques. This would not work in the case of testing mappings against a legacy database.

RobDemo
A: 

i think that it's very important to do this testing with your real db, to see that his tables definition r ok, so i'v developed a very simple class that perform a crud test on a mapped entity and roll back at the end;

 internal class GenericMappingTesterWithRealDB<T> where T : IIdentifiable
{
    public T EntityToTest { get; set; }
    public Func<T, object> PerformEntityManipulationBeforeUpdate { get; set; }
    public GenericMappingTesterWithRealDB()
    {
        Assume.That(SessionFactoryProvider.NewSession,Is.Not.Null);
    }

    public void RunTest()
    {
        using (ISession session = SessionFactoryProvider.NewSession)
        using (ITransaction transaction = session.BeginTransaction())
        {
            try
            {
                session.Save(EntityToTest);
                var item = session.Get<T>(EntityToTest.ID);
                Assert.IsNotNull(item);
                if (PerformEntityManipulationBeforeUpdate != null)
                {
                    PerformEntityManipulationBeforeUpdate.Invoke(EntityToTest);
                }
                session.Update(EntityToTest);
                session.Delete(EntityToTest);
                session.Save(EntityToTest);
            }
            catch (Exception e)
            {
                Assert.Fail(e.Message, e.StackTrace);
            }
            finally
            {
                transaction.Rollback();
            }
        }
    }
}

IIdentifiable in my project is the most basic interface of my entities

the class is using the nunit.framework but u can do it with every testing framework u want

sessionfactoryprovider needs to supply the isession obj

here is a sample of use

/// <summary>
/// Testing the mapping of our entities.
/// there must be a server connection for this kind of test.
/// </summary>
[TestFixture]
internal class someMappingTest
{
    [Test(Description = "Check the Encoding Profile FluentNHibernate Mapping")]
    [Timeout(20000)]
    public void checkthatMappingWorks()
    {
        // creatw the new entity
        TestedType testOn = new TestedType();

        // set the initialization values
        testOn.Name = "TestProfileExecution";

        // create the test object
        new GenericMappingTesterWithRealDB<TestedType>
        {
            // assign an entity
            EntityToTest = testOn,

            // assign new values for update check
            PerformEntityManipulationBeforeUpdate =
                delegate(TestedType testedTypeBeingTested)
                    {
                        return testedTypeBeingTested.Name = "Updateing Test";
                    }
        }.
        // call run test to perform the mapping test.
        RunTest();

    }
}
Chen Kinnrot
+3  A: 

Try setting the IsolationLevel on the transaction. This snippet worked for me:

using (var trans = _session.BeginTransaction(IsolationLevel.ReadUncommitted))
{
    new PersistenceSpecification<Event>(_session)
        .CheckProperty(p => p.StartTime, new DateTime(2010, 1, 1))
        .VerifyTheMappings();
    trans.Rollback();
}
leebrandt
Gets my Vote, exactly what I was looking for!
cgreeno