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

时间:2015-06-12 23:26:56

标签: entity-framework transactions entity-framework-6.1

我正在寻找一种快速方法来清理我的表数据,并使用EF进行集成测试。

每个人似乎都围绕其测试方法包装一个事务,并在测试后处理该事务。

这样,数据永远不会写入表格。

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

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

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

更新

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");          
        }
}

1 个答案:

答案 0 :(得分:2)

  

因为永远不会触及数据库

当然感动了。事务中发生的所有事情都发生在数据库中。身份值和序列(如果有的话)递增,触发激发,检查参照约束等等。唯一的事情是,它是孤立地发生的,最后一切(除了增加的身份和序列)被还原。

  

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

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

但是你应该注意一些限制。

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