EF4 Code First, TDD, CRUD, and Transactions

故事扮演 提交于 2019-12-21 02:56:25

问题


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
            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?


回答1:


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.



来源:https://stackoverflow.com/questions/4382139/ef4-code-first-tdd-crud-and-transactions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!