Rollback for database testing

Roy Osherove had a good speak in TechEd Barcelona 2007, about using the roll back attribute for database testing, and it works really well, keeping the test case isolated. Except in cases where the production code ignores transactions that are higher up in the hierarchy. This will happen if the TransactionOption is RequiresNew

Roy suggested to always use: Supported, but we believe that there should be a way to test you code even if you require and need to use another transactions.

So here is how I would do it with TypeMock.
I would create a new attribute for the rollback and make sure that all future TransactionOptions are Mocked.

This way our test will look like:

[TestMethod,Rollback,VerifyMocks]
public void MyDatabaseTest()
{
}

Here is the code, to enable this (for any test framework) simple add the attribute.

[AttributeUsage(AttributeTargets.Method)]
public sealed class RollBackAttribute : DecoratorAttribute

    public override object Execute() 
    { 
        // Start transaction
        ServiceConfig config = new ServiceConfig();
        config.Transaction = TransactionOption.RequiresNew;
        ServiceDomain.Enter(config);
        // make sure that all future Transactions rely on this transaction by mocking all sets to the Transaction
       Mock serviceConfigMock = MockManager.MockAll<ServiceConfig>(Constructor.NotMocked);
       serviceConfigMock.ExpectSetAlways("Transaction");

       try
       {
            // run our tests
           return base.CallDecoratedMethod(); 
        } finally
        { 
            // clear unused mocks
            serviceConfigMock.Clear();

             // rollback database
            if(ContextUtil.IsInTransaction)
            { 
                ContextUtil.SetAbort();
            }
            ServiceDomain.Leave();
        }
   } 
}

Add Comment

Required fields are marked *. Your email address will not be published.