2010-06-18 44 views
2

我已經編寫了一些針對.net代碼的測試,這些測試調用了對我的SQL Server的調用。看起來使用System.Transactions是回滾對數據庫所做任何修改的最佳選擇。我知道一些純粹主義者會建議我可能要嘲笑數據庫,但我不會走這條路;這不是純粹的單元測試。SQL Server和TransactionScope(帶有MSDTC):偶爾無法獲得連接

當我編寫並運行多個測試時,它的工作原理與預期完全相同。我只是簡單地把代碼初始化,並在測試設置和測試拆卸方法中放棄.net事務。這似乎是一個很好的解決方案。

但是,我遇到的問題是,當我嘗試運行這些測試中的100個時,它們中的很多將會拋出異常,即使它們在逐個運行時仍然無法連接到SQL Server。更糟糕的是,當我運行我的測試時,數據庫中的表偶爾會被鎖定。我必須要求我的DBA手動刪除鎖。

很多人都知道,在開發工作站上運行的代碼上(如運行此測試時)對SQL服務器使用TransactionScope將使.net框架使用MSDTC。

下面是一個代碼示例來說明我在做什麼:

<TestInitialize()> Public Sub MyTestInitialize() 
    _scope = New System.Transactions.TransactionScope(_ 
     System.Transactions.TransactionScopeOption.Required, New TimeSpan(0, 2, 0)) 
End Sub 
<TestCleanup()> Public Sub MyTestCleanup() 
    _scope.Dispose() 
End Sub 

<TestMethod()> Public Sub CurrentProgramUser_Get_UserID() 
    Dim ProgramSessionId As String 
    Dim CurrentProgramUserId As Integer 
    Dim dSession As ProgramSession 
    CurrentDCMAUserId = Convert.ToInt32(_ 
    SqlHelper.ExecuteScalar(testDcmaConnString, System.Data.CommandType.Text, _ 
    "INSERT into Program_Users(UserName,FirstName,LastName) " & _ 
    "VALUES('GuitarPlayer','Bob','Marley')" & _ 
    "SELECT IDENT_CURRENT('Program_users') ") _ 
         ) 
    ProgramSessionId = session.getCurrentSession() 
    session.WriteUserParam("Program", ProgramSessionId, "USERID", CurrentProgramUserId.ToString(), testSource, testConnString) 

    Dim readValue As Integer 
    readValue = session.User.UserID 

    Assert.AreEqual(CurrentProgramUserId, readValue) 
End Sub 

正如你所看到的,沒有什麼特別看中這裏。我只是有一種測試方法,它會將一些東西寫到我的數據庫中,以便我的方法找到。這只是一個例子;還有很多其他的測試。

我的測試邏輯看起來很健全。什麼可能導致我的測試不僅失敗,而且偶爾將用戶鎖定在表外?

+2

該鎖定可能與未完成的事務有關(或未發生錯誤回滾)。請確保您提交/回滾正確 – 2010-06-18 21:05:14

回答

2

我發現了這個問題。我正在測試的一種方法是使用SqlDataReader對象。顯然,Close()方法必須在SqlDataReader超出範圍才能釋放連接之前調用,但在我的情況下,我沒有這樣做。

只需將mySqlDataReader.Close()添加到待測試方法的末尾即可解決問題。此外,測試這種特定方法的測試方法是由超過100個測試用例進行數據驅動的,因此解釋了我可能會如何用盡連接。

+0

哪個源代碼正確,對嗎? – Kiquenet 2010-07-21 16:14:21

+0

不,這實際上是另一種測試方法......長而短是連接不一定在測試之間釋放。 – 2010-07-21 17:59:54