2012-04-13 86 views
6

我正在使用MSTest通過MySQL Connector和EntityFramework 4.3對MySQL 5.5.19數據庫運行一些自動化測試。嵌套的TransactionScope在測試中失敗

我試圖在我的DB訪問類庫中使用TransactionScope來在需要時執行回滾。另外,在我的測試代碼中,我希望使用TransactionScope在每次測試之前將數據庫恢復到已知狀態。我使用TestInitializeTestCleanup方法來完成此操作。那些看起來像這樣:

[TestInitialize()] 
public void MyTestInitialize() 
{ 
    testTransScope = new TransactionScope(TransactionScopeOption.RequiresNew); 
} 

[TestCleanup()] 
public void MyTestCleanup() 
{ 
    Transaction.Current.Rollback(); 
    testTransScope.Dispose(); 
} 

根據在初始化函數的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.StatusTransactionStatus.Aborted,所以我很確定這是發生了什麼。

大,所以我想我會改變我的AddDesert方法就像上面那樣看起來除了我要嵌套事務範圍,而不是使用環境之一,我的一些using線外表看起來是這樣的:

using (var transScope = new TransactionScope(TransactionScopeOption.RequiresNew)) 

這裏的意圖是我可以嵌套這些事務範圍,讓我的生產代碼中的回滾發生,然後在我的測試代碼中仍然檢查我的Assert

但是我發現的是,我得到以下錯誤:

System.IO.IOException:無法讀取從傳輸連接數據:A連接嘗試失敗,因爲連接的方沒有正確響應後一段時間或建立的連接失敗,因爲連接的主機無法響應。

想法?

+0

請張貼堆棧跟蹤和它發生在哪裏的代碼。 – usr 2012-04-13 17:09:23

回答

0

非常好的問題。當您在回滾後的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()); 
      } 
     } 
    }