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();
}
}
}
Leave a Reply