我的测试中有以下基础对象
[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
答案 0 :(得分:3)
您需要更改TestCleanup方法,现在您处理TransactionScope,我相信它实际上是在进行隐式提交吗? (你会认为你需要调用Complete()吗?),因为没有错误它不会回滚事务。
试试这个
[TestCleanup]
public virtual void TestCleanup()
{
// using System.Transactions;
Transaction.Current.Rollback();
_transactionScope.Dispose();
}
答案 1 :(得分:1)
我知道这个问题有点陈旧,但它可能会帮助那些将来可能/将要在这方面挣扎的人,就像我之前做的那样。所以,如果你正在使用
以下代码无效。
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
}
}
我在创建数据库上下文之前尝试(并且无法工作)创建TransactionScope,反之亦然。我认为它与EF本身有关,我认为它封装在他们自己的交易或其他任何事情中。我没有深入挖掘这一部分。无论如何,这是我用EF和事务做的,以确保在单元测试完成后你的单元测试DB是干净的。
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;
}
}
希望此时能帮助其他人搜索: - )
答案 2 :(得分:1)
在 .NET Core 中,async Task
[TestInitialize]
方法不受支持,会导致您描述的行为。
异步 [TestInitialize]
方法似乎在与 [TestMethod]
本身不同的线程上下文中运行,即使 TransactionScopeAsyncFlowOption.Enabled
在 TransactionScope 的选项中设置。 Transaction.Current
在测试方法中将为 null,并且当 [TestCleanup]
处置 TransactionScope 时,任何更改都不会回滚。
不幸的是,there are no plans 支持 TestInitialize 方法中的异步流,尽管这适用于较旧版本的 .NET(至少是 .NET Framework 4.8)。
目前唯一的解决方法是使 [TestInitialize]
方法非异步并使 .Wait()
/ .Result
成为您的异步调用,但请对上面的 GitHub 问题点赞以表示对此功能的支持.
答案 3 :(得分:0)
如果您使用的是VS2005或VS2008(不确定2010年),则可以在测试方法完成后尝试MSTestExtensions进行自动数据库事务回滚。我已经将它与MS SQLServer一起使用,它运行的是分布式事务处理协调器服务。
我知道这可能不是您正在寻找的,但它可能对您的情况有所帮助。
答案 4 :(得分:0)
我认为你在这里要实现的是创建一个通用的Test类来实现初始化和清理,这样你就不必为每个测试重复那段代码,这是正确的吗?你甚至确定那些方法甚至被称为?请注意,您不能继承[TestInitialize]和[TestCleanup],因此您必须从sublcass调用这些方法。 (见https://stackoverflow.com/a/15946140/1638933)。
答案 5 :(得分: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();
}