使用事务的缺点配置实体框架集成测试

Eli*_*eth 6 entity-framework transactions entity-framework-6.1

我正在寻找一种快速的方法来清理我的表数据与EF进行集成测试.

每个人似乎围绕其测试方法包装事务并在测试后处理事务.

这样,数据永远不会写入表中.

像插入的新自动ID这样的东西仍在工作,但我问自己,与.commit()交易相比,这种方法真的可靠.

使用这种方法有什么缺点似乎不是真正的集成测试,因为数据库永远不会被触及......

或者换句话说是否存在错误的情况,如果没有commit()使用事务而不作为异常弹出?

UPDATE

public abstract class IntegrationTestsBase
    {
        protected TransactionScope TransactionScope;

        public abstract void TestSetup();
        protected void InitTestSetupOnTable(string tableName)
        {
            TransactionScope = new TransactionScope();

            using (var context = new TGBContext())
            {
                var cmdCommand = string.Format("DBCC CHECKIDENT ({0}, RESEED, 1)", tableName);
                context.Database.ExecuteSqlCommand(cmdCommand);
                context.SaveChanges();
            }
        }

        [TestCleanup]
        public void TestCleanup()
        {
            TransactionScope.Dispose();
        }
    }

[TestClass]
public class MyTests : IntegrationTestsBase
{
        [TestInitialize]
        public override void TestSetup()
        {
            base.InitTestSetupOnTable("MyTableName");          
        }
}
Run Code Online (Sandbox Code Playgroud)

Ger*_*old 2

因为数据库从未被触及

肯定是被感动了。事务中发生的所有事情都发生在数据库中。身份值和序列(如果有)递增,触发触发器,检查引用约束等。唯一的事情是,它是孤立发生的,最终所有内容(除了递增的身份和序列)都被恢复。

使用这种方法有什么缺点吗?

并不真地。我在自己的代码中广泛使用这种方法,它有很大的优点。绿色测试提供了非常高水平的保证。我永远不会对使用模拟上下文和 的“真实”单元测试感到安全DbSet(尽管我对许多其他事情使用单元测试)。

但您应该注意一些限制。

  • 身份/序列值不是确定性的,因此您无法断言它们。正如我所说,这些值不会回滚。如果您确实需要在该区域进行断言,则可以在每次测试后重置身份/序列。
  • 我们永远无法通过这种方法来测试并发问题。
  • 在没有 DTC 启动的情况下,您无法打开与另一个数据库的连接,甚至无法打开与同一数据库的连接,如果其连接字符串在最细微的细节上有所不同(例如不同的应用程序名称或不同的 MARS 设置)。在应用程序代码中,这将是这是可能的,因为这些不同的调用不会被包装在TransactionScope. 因此,也许并非所有应用程序路径都可以通过这种方式轻松测试。
  • 开发人员应该使用自己的测试数据库副本。如果多个开发人员(可能还有构建服务器)在同一个数据库上运行测试,他们可能会彼此陷入僵局。