EF4 Code First,TDD,CRUD和Transactions

时间:2010-12-07 22:07:07

标签: transactions entity-framework-4 tdd code-first

过去,我在创建看起来像这样的数据访问/存储库代码时,已经为简单的CRUD操作编写了单元测试:

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
            transaction.Rollback();
        }
    }
}

今天我正在搞乱EF4 Code First,我意识到我不知道这个测试场景如何在Entity Framework词典中进行翻译。看来,如果我致电DbContext.SaveChanges(),它会保存提交,无论是否调用了AcceptAllChanges()。即使使用ObjectContext而不是DbContext,我也无法弄清楚如何在不手动清理创建的任何模拟/测试对象的情况下重新创建这个简单的测试场景。我确实阅读了this article on MSDN,但TransactionScope也没有真正的Rollback类型方法。我是否使用TransactionScope而从不致电Complete?是否有其他方法或方式使用DbContext和/或ObjectContext以便在单元测试期间回滚?我是否需要使用EF4 Code First完全重新调整我对TDD的思考?

1 个答案:

答案 0 :(得分:8)

ObjectContext本身不会暴露事务行为。您必须自己在事务中包装EF代码。简单的方法是使用TransactionScope。如果您没有在作用域上调用Complete方法并将其处理掉,它将执行回滚。我们通常使用基类进行此类集成测试:

[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;
        }
    }
}

所有测试类都派生自此类。在派生类中的每个TestInitialize之前调用TestMethod,并在每个TestCleanup之后调用TestMethod,因此您的测试根本不需要处理事务。