数据访问层在同时运行多个测试时引发事务异常

本文关键字:测试 异常 事务 运行 访问 数据 | 更新日期: 2023-09-27 18:31:07

我正在对基于实体框架构建的数据访问层(我知道它被称为集成测试等)进行单元测试。我有 10 多个测试,通常它们非常广泛,因为单个测试是检查例如某个实体的整个 CRUD。当我一个接一个地运行它时,一切都很好。我刚刚连续运行了 7 次这些测试之一,结果总是积极的。但是当我同时运行所有测试时,大约一半的测试会引发以下异常:

系统.事务

.事务中止异常:事务具有 中止。

这非常令人担忧,因为我担心频繁拨打 DAL 可能会有一些问题。

我正在使用xUnit 1.9.2,VisualStudio 2012(带有xUnit测试运行器)和Entity Framework 5.0.0。DAL 使用提供程序连接到 Oracle 数据库 ODP.NET。

编辑:

我的 DAL 包含以下事务处理方法:

protected SomeDb _context = new SomeDb(); //It's DbContext
protected TransactionScope _transactionScope;
public void BeginTransaction()
{
    _transactionScope = new TransactionScope();
}
public void Rollback()
{
    _transactionScope.Dispose();
}

另一方面,我的测试方法如下所示:

[Fact]
public void DAL_Entity_CRUD()
{
    #region Arrange
    IDataAccess _dataAccess = new DataAccess();
    //Somecode
    #endregion
    #region Act
    _dataAccess.BeginTransaction();
    //Somecode
    _dataAccess.Rollback();
    #endregion
    #region Assert
    //Somecode
    #endregion
}

但是我最近发现它应该是:

IDataAccess _dataAccess = new DataAccess();
try
{
    _dataAccess.BeginTransaction();
    //Some code
    _dataAccess.Rollback();
}
catch
{
    _dataAccess.Rollback();
    throw;
}

我说的对吗?

无论如何,我的 DAL 实现了 IDisposable,所以据我所知,在测试方法结束时处理事务范围和 DbContext 时应该关闭事务......

~DataAccess()
{
    this.Dispose(false);
}
protected bool Disposed { get; private set; }
public void Dispose()
{
    // Dispose of unmanaged resources.
    this.Dispose(true);
    // Suppress finalization.
    GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
    if (!this.Disposed)
    {
        if (disposing)
        {
            // Perform managed cleanup here.
            _transactionScope.Dispose();
            _context.Dispose();
        }
        // Perform unmanaged cleanup here.
        this.Disposed = true;
    }
}

数据访问层在同时运行多个测试时引发事务异常

在xUnit项目中查找(并发布,以便我们可以看到)TransactionScope的任何用法。

如果我不得不猜测,我会说您将整个测试运行包装在一个事务中,而不是包装每个单独的测试。 此"全局异常"是由于在夹具安装程序类 (IUseFixture) 中创建的事务而显式发生的,或者是通过在测试类构造函数中创建事务然后未在测试类的一次性方法中释放它而意外发生的,从而导致新事务嵌套。

无论哪种情况,如果其中一个测试方法未调用 .在事务上完成(从业务角度来看,这可能是正确的),这会使整个事务受到怀疑,从而导致任何以后的 TransactionScope 构造函数和 。完成失败的方法。 该全局异常也可能超时,因为它现在涵盖多个测试。 我相信默认值是一分钟或 30 秒。