2008-10-07 82 views
4

在這個asp.net中,我正在清理它可能發生死鎖。我想確保代碼正確處理它們,所以我試圖編寫NUnit測試來觸發死鎖.....我可以在Nunit中創建數據庫死鎖測試嗎?

DAO被實體分割。每個實體都有一組測試,這些測試由Startup()和Teardown()方法包圍,這些方法創建一個事務範圍,然後在測試完成後將其回滾。這適用於其他任何事情,但對於死鎖完全沒有用處。

如何使用可以可靠複製的TransactionScope和SQL2000(即涉及MSDTC)來設置和運行「死鎖」測試? 更多詳細信息:我知道有這樣一種情況,即如果兩個用戶調用具有不同的特定數據值的兩個函數,那麼死鎖可以得到的結果。我如何在NUNIT中模擬這個 - 並且使得始終發生

是的,我的確從「爲什麼不停止發生在第一個位置的死鎖」行動計劃開始,但我無法控制可能發生死鎖的代碼 - 我只是調用函數他們可能會陷入僵局。

回答

2

如果您的死鎖導致拋出異常,您希望使用模擬對象來模擬拋出的異常。

的基本想法是,你告訴你的Mock對象框架(我喜歡TypeMock)拋出一個異常,而不是,是這樣的:

MockObject mo = MockManager.MockObject(typeof(MyDeadlockException)); 
mock.ExpectAndThrow("MyMethod", (MyDeadlockException)mo.Object); 

的想法基本上是其他嘲諷框架相同。

+0

我喜歡這個想法。我有模擬框架的想法,但從未使用過。我假設一個「ExpectAndThrow」方法實際上會導致異常被拋出,所以我的代碼可以捕獲它。我會進一步研究。 – 2008-10-10 10:29:17

+0

這正是它所做的。我沒有使用它,但如果你有預算問題,Rhino.Mocks是免費的:http://ayende.com/projects/rhino-mocks.aspx – 2009-08-21 14:16:08

0

如果您的交易中有一項測試只是等待5分鐘,那該怎麼辦?或者,您只需編寫一個測試來啓動事務,創建新記錄,然後更新該記錄而不提交。然後,開始新的事務並嘗試讀取已創建並且當前正在更新的記錄。你會在那裏陷入僵局。

+0

在同一線程中創建兩個事務不能使用TransactionScope產生死鎖。如果我創建了一個txn,然後創建另一個不提交第一個,第二個嵌套在第一個..... – 2008-10-08 07:38:57

0

如果您手動鎖定表並始終將其鎖定,該怎麼辦?那麼,你對該表採取的任何行動都會產生死鎖情況?

+0

「手動」使用MSDTC創建事務並不簡單。當然,我可以在查詢分析器中開始一個事務,但這不是一個分佈式事務,發生的一切就是它阻止MSDTC事務從事任何數據庫工作,直到我在查詢分析器中「回滾」。 – 2008-10-08 07:39:34

0

來到這個盲目,但它有可能在您的TestSetup方法實際上創建一個SQLConnection到您的數據庫?那麼,使用它,你可以發出一個命令來鎖定表或採取一些行動來鎖定一個記錄或頁面?那樣,它會超出你正在進行的任何其他交易嗎?看起來這將是一個你已經考慮過的選項。我錯過了你的情況?

+0

我認爲創建死鎖的先決條件將是發行交易的兩個獨立流程。在一個進程中創建「人造」鎖並不會強制造成死鎖 - 它強制「等待」資源變爲空閒。我希望有一種方法可以在NUNIT中進行模擬。 – 2008-10-08 07:43:36

+0

我沒有看到在手動強制之外的方法。現在,這可能意味着你在NUnit中手動強制它,但你仍然手動強制它。您只需創建生成死鎖場景的情況。 – 2008-10-08 18:00:49

0

對於單元測試,您可能希望避免實際使用數據庫。你怎麼知道你有一個僵局。你應該測試一下條件,告訴你有一個死鎖並在你的測試中創建它。

一個模擬是一個理想的模仿,如果你調用一個服務,它會返回一個錯誤。只需讓模擬返回您所期望的錯誤。如果您正在等待超時或其他事情,那麼同樣的事情也適用。

一般來說,單元測試應該只運行在被測試的代碼上,不要依賴任何其他代碼或組件。這就是說 - 數據庫本質上是另一個組件,你可能正在做一些使用nunit來驅動它們的功能測試。

在這種情況下,您實際上必須創建死鎖情況,但鎖定記錄或表,然後調用試圖使用相同記錄並處理響應的組件。