c# – 嵌套的TransactionScope在测试中失败
我正在使用MSTest通过
MySQL Connector和使用EntityFramework 4.3对MySQL 5.5.19数据库运行一些自动化测试.
我正在尝试在我的数据库访问类库中使用TransactionScope在需要时执行回滚.另外,在我的测试代码中,我希望在每次测试之前使用TransactionScope将数据库恢复到已知状态.我使用TestInitialize和TestCleanup方法来完成此任务.那些看起来像这样: [TestInitialize()] public void MyTestInitialize() { testTransScope = new TransactionScope(TransactionScopeOption.RequiresNew); } [TestCleanup()] public void MyTestCleanup() { Transaction.Current.Rollback(); testTransScope.Dispose(); } 基于在Initialize函数中构造TransactionScope对象,我相信我应该得到一个新的事务范围(没有“环境”存在,所以我相信这个“??.RequiresNew”在技术上并不重要“.Required”会产生相同的结果.由于我没有指定超时值,它为我提供了默认超时,我理解为60秒.我给定测试运行的时间充足. 我有一个名为AddDessert(DessertBiz dessertBizObject)的函数,其部分看起来像这样: using (var transScope = new TransactionScope(TransactionScopeOption.Required)) { try { // ... context.Desserts.Add(dessert); context.SaveChanges(); var dessertId = dessert.Id; DoOtherDessertStuff(dessertId,dessertBizObject); transScope.Complete(); } catch (InvalidOperationException ex) { Console.WriteLine(ex.ToString()); } } 并且我的一个测试调用了这个函数. 由于我在这里指定了TransactionScopeOption.Required,我希望它将使用MyTestInitialize函数创建的“环境”事务范围. 我的测试安排使这个DoOtherDessertStuff函数失败并抛出异常,所以调用transScope.Complete();不会发生,并且在退出AddDessert函数中的using块时会自动进行回滚. 我在这里遇到的问题是,由于它使用MyTestInitialize函数中创建的环境事务范围,因此我的测试Assert调用不会发生,因为事务范围回滚发生了 – 至少这是我认为正在发生的事情.我验证了Transaction.Current.TransactionInformation.Statusis TransactionStatus.Aborted,所以我觉得很确定这是发生了什么. 太棒了,所以我想我会改变我的AddDesert方法看起来与上面完全一样,除了我会嵌套一个事务范围而不是使用环境范围,一些我使用的行看起来像这样: using (var transScope = new TransactionScope(TransactionScopeOption.RequiresNew)) 这里的意图是我可以嵌套这些事务范围,让我的生产代码中的回滚发生,然后仍然在我的测试代码中检查我的Asserts. 但我发现我得到以下错误: System.IO.IOException:无法从传输连接读取数据:连接尝试失败,因为连接方在一段时间后没有正确响应,或者由于连接的主机无法响应而建立的连接失败. 想法? 解决方法
非常好的问题.在回滚后在testmethod中引用datacontext时,它将不可用.你需要压制它.您无需指定必需的选项.这是默认选项.
测试方法: [TestMethod()] public void CreateTestCheckContextCorrectly() { MailJobController target = new MailJobController(); target.AddDessert("dessert for Omer"); //With suppress,even if you rollback ambient trans,suppress will ignore ambient trans. You need to reference new context,previous context from controller may be disposed. using (var suppressscope = new TransactionScope(TransactionScopeOption.Suppress)) { var newdbcontextref = new DbEntities(); int recordcount = newdbcontextref.StatusDefinitions.Where(x => x.Name == "dessert for Omer").Count(); Assert.AreEqual(0,recordcount); } } 控制器方法: public void AddDessert(string dessert) { using (var transScope = new TransactionScope()) { try { // ... StatusDefinition statusDefinition = new StatusDefinition() {Name = dessert}; db.StatusDefinitions.AddObject(statusDefinition); db.SaveChanges(); Console.WriteLine("object id:"+statusDefinition.StatusDefinitionId); throw new Exception("hee hee"); transScope.Complete(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |