3

我的测试中有以下基础对象

[TestClass]
public abstract class TestClassBase
{
    private TransactionScope _transactionScope;

    [TestInitialize]
    public virtual void TestInitialize()
    {
        _transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { Timeout = new TimeSpan(0, 10, 0) });
    }

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

我有一个执行以下操作的测试

[TestMethod]
public void SaveToDatebaseTest(
{
     Program program = new Program();         
     program.Name = "Unit Test Program, I should not exists, when Test is done";
     ProgramManager programManager = new ProgramManager()
     programManager.Save(program);
}

当我运行测试时,记录仍然存在于数据库中。

我想避免在每个测试方法中使用 TransactionScope

4

6 回答 6

2

您需要更改您的 TestCleanup 方法,现在您 Dispose 的 TransactionScope,我相信这实际上是在执行隐式提交?(你会认为你需要调用 Complete() 吗?),因为没有错误,它不是回滚事务。

尝试这个

[TestCleanup]
public virtual void TestCleanup()
{
    // using System.Transactions;
    Transaction.Current.Rollback();
    _transactionScope.Dispose();
}
于 2011-02-16T17:40:19.057 回答
1

i know this question is kind of old, but it may help out someone who might/will be struggling on this in the future like i just did earlier. so if you're using

  • Entity Framework
  • Nunit (v3)

the code below won't work.

class A
{
     private TransactionScope _trans;

     [SetUp]
     public void setup()
     {
        _trans = new TransactionScope();
     }

     [TearDown]
     public void done()
     {
        if(_trans != null)
          _trans.Dispose();
     }

     [Test]
     public void doSomeDbWrite()
     {
         //your code to insert/update/delete data in db
     }
}

I have tried (and doesn't work) creating the TransactionScope before creating the DB Context or the other way around. I think it has something to do with EF itself which i suppose is encapsulated in their own transactions or whatever. i did not dig deeper on that part. anyway, here's how i did it with EF and transactions to ensure that your unit test DB is clean after the unit test is done.

class A
{
     private DbContext_DB;
     private DbContextTransaction _trans;

     [SetUp]
     public void setup()
     {
        DB = new DbContext();//create your db context
        _trans = DB.Database.BeginTransaction();
     }

     [TearDown]
     public void done()
     {
        _trans.Rollback();
        DB = null;
     }
}

Hopefully it will help others searching for this at this time :-)

于 2017-11-08T02:51:49.473 回答
1

在 .NET Coreasync Task [TestInitialize]中,方法不受支持,会导致您描述的行为。

异步[TestInitialize]方法似乎在与[TestMethod]自身不同的线程上下文中运行,即使TransactionScopeAsyncFlowOption.Enabled在 TransactionScope 的选项中设置也是如此。将在测试方法中为空,并且在处置 TransactionScopeTransaction.Current时任何更改都不会回滚。[TestCleanup]

不幸的是,没有计划在 TestInitialize 方法中支持异步流,尽管这在旧版本的 .NET(至少 .NET Framework 4.8)中有效。

目前唯一的解决方法是使[TestInitialize]方法非异步和.Wait()/.Result您的异步调用,但请投票支持上面的 GitHub 问题以显示对此功能的支持。

于 2021-03-18T21:04:51.087 回答
0

我认为您在这里尝试实现的是创建一个实现初始化和清理的通用测试类,这样您就不必为每个测试重复该代码,对吗?您是否确定甚至调用了这些方法?请注意,您不能将 [TestInitialize] 和 [TestCleanup] 子类化,因此您必须从 sublcas 中调用这些方法。(见https://stackoverflow.com/a/15946140/1638933)。

于 2015-04-21T08:44:12.777 回答
0

如果您使用的是 VS2005 或 VS2008(不确定 2010),您可以在测试方法完成后尝试MSTestExtensions进行自动数据库事务回滚。我已经将它与 MS SQLServer 一起使用,它的分布式事务协调器服务正在运行。

我知道这可能不是您正在寻找的,但它可能对您的情况有所帮助。

于 2011-02-08T03:54:37.727 回答
0

我有同样的问题,但我使用以下代码来解决问题也许它可以帮助你:

    private readonly TransactionScope _scope;

    public MyTests()
    {
        var options = new TransactionOptions()
        {
            IsolationLevel = IsolationLevel.Snapshot
        };

        _scope = new TransactionScope(TransactionScopeOption.Required, options,  TransactionScopeAsyncFlowOption.Enabled);
      }

      [TestCleanup]
      public void Cleanup()
      {
          _scope.Dispose();
      }
于 2019-08-12T20:31:07.550 回答