In the past, I've written unit tests for simple CRUD operations when creating data access/repository code that look something like this:
using(var connection = new WhateverConnection(connectionString))
{
connection.Open();
using(var transaction = connection.BeginTransaction())
{
try
{
//test the CRUD operation
}
finally
{
//gets rid of any stuff created during the test
开发者_JS百科transaction.Rollback();
}
}
}
I was messing around with EF4 Code First today, and I realized that I have no idea how this testing scenario translates in the Entity Framework lexicon. It seems that, if I call DbContext.SaveChanges()
, it saves and commits, regardless of whether or not AcceptAllChanges()
was called. Even using ObjectContext
instead of DbContext
, I can't figure out how this simple test scenario can be recreated without manually cleaning up any mock/test objects created. I did read this article on MSDN, but TransactionScope
doesn't really have a Rollback
type method either. Do I use TransactionScope
and never call Complete
? Is there another method or manner of using DbContext and/or ObjectContext in order to Rollback during unit tests? Do I need to completely re-adjust my thinking for TDD with EF4 Code First?
ObjectContext
itself does not expose transactional behavior. You have to wrap EF code in transaction by yourself. The easy way to do it is using TransactionScope
. If you don't call Complete
method on the scope and dispose it, it will perform rollback. We are usually using base class for this type of integration tests:
[TestClass]
public abstract class TransactionTestBase
{
private TransactionScope scope = null;
[TestInitialize]
public virtual void TestInitialize()
{
scope = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
});
}
[TestCleanup]
public virtual void TestCleanup()
{
if (scope != null)
{
scope.Dispose();
scope = null;
}
}
}
All test classes derive from this class. TestInitialize
is called before each TestMethod
in derived class and TestCleanup
is called after each TestMethod
so your tests don't have to deal with transaction at all.
精彩评论