C# TransactionScope未在MSTest中回滚

C# TransactionScope未在MSTest中回滚,c#,unit-testing,transactions,mstest,vs-unit-testing-framework,C#,Unit Testing,Transactions,Mstest,Vs Unit Testing Framework,我的测试中有以下基本对象 [TestClass] public abstract class TestClassBase { private TransactionScope _transactionScope; [TestInitialize] public virtual void TestInitialize() { _transactionScope = new TransactionScope(TransactionScopeOptio

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

[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如果您使用的是VS2005或VS2008(不确定是否为2010),那么可以在测试方法完成后尝试自动回滚数据库事务。我在MS SQLServer中使用过它,它的分布式事务协调器服务正在运行


我知道这可能不是您想要的,但可能对您的情况有所帮助。

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

试试这个

[TestCleanup]
public virtual void TestCleanup()
{
    // using System.Transactions;
    Transaction.Current.Rollback();
    _transactionScope.Dispose();
}

我认为您在这里试图实现的是创建一个实现初始化和清理的通用测试类,这样您就不必为每个测试重复该代码,对吗?你确定这些方法被调用了吗?请注意,您不能将[TestInitialize]和[TestCleanup]子类化,因此必须从子类调用这些方法。(请参阅)。

我知道这个问题有点老了,但它可能会帮助那些将来可能/将在这个问题上苦苦挣扎的人,就像我刚才所做的那样。所以如果你使用

  • 实体框架
  • 努尼特(v3)
下面的代码不起作用

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
     }
}
在创建DB上下文之前或以其他方式创建TransactionScope之前,我已经尝试过(但没有成功)。我认为这与EF本身有关,我认为EF是封装在他们自己的事务中的。我没有在那一部分深入挖掘。无论如何,下面是我如何使用EF和事务来确保单元测试完成后单元测试数据库是干净的

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

希望它能帮助其他人在这个时候搜索:-)

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

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

在.NET Core
异步任务中
[TestInitialize]
方法不受支持,将导致您描述的行为

异步
[TestInitialize]
方法似乎在与
[TestMethod]
本身不同的线程上下文中运行,即使在TransactionScope的选项中设置了
TransactionScopeAsyncFlowOption.Enabled
<代码>事务。当前的将在测试方法中为空,并且当
[TestCleanup]
处理事务范围时,任何更改都不会回滚

不幸的是,尽管在较旧版本的.NET(.NET Framework 4.8)中可以使用异步流,但在TestInitialize方法中仍然支持异步流


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

这是dotnet core和async之前的一个问题是的,我肯定是。