【问题标题】:Data access layer throws transaction exceptions when running multiple tests at the same time数据访问层同时运行多个测试时抛出事务异常
【发布时间】:2014-11-21 20:32:17
【问题描述】:

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

System.Transactions.TransactionAbortedException : 事务有 中止。

这非常令人担忧,因为我担心频繁调用 DAL 可能会出现问题。

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

编辑:

我的 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,据我所知,在测试方法结束时处理 TransactionScope 和 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;
    }
}

【问题讨论】:

  • 你能不能四处挖掘,看看能不能找到更详细的错误?理想情况下,如果这将成为 Oracle 层或 Oracle 数据库的问题,我们希望看到一些 ORA 错误。

标签: c# entity-framework unit-testing odp.net xunit


【解决方案1】:

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

如果我不得不猜测,我会说您将整个测试运行包装在一个事务中,而不是包装每个单独的测试。这个“全局异常”是由于在夹具设置类(IUseFixture)中创建的事务而显式发生的,或者是通过在测试类构造函数中创建事务然后没有在测试类的一次性方法中处理它而意外发生的,从而导致新事务筑巢。

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

【讨论】:

  • 感谢您的建议。请参阅已编辑的原始帖子。如您所见,我将每个测试都包装在一个单独的事务中。如果您能在我发布的代码中看到任何错误,我将不胜感激,否则我会遵循您的有用建议。
  • 我认为这是一个简单的逻辑错误。你的析构函数调用 dispose 时带有一个“false”参数,这意味着你的“if(disposing)”失败并且交易永远不会被释放。
猜你喜欢
  • 1970-01-01
  • 2017-04-19
  • 1970-01-01
  • 2012-08-07
  • 2016-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-07-15
  • 2013-01-20
相关资源
最近更新 更多