2016-02-05 100 views
1

當我運行我的xUnit單元測試時,有時會出現一個錯誤消息,例如「事務(進程ID 58)在另一個進程上死鎖在鎖資源上並且已被選爲死鎖受害者」測試,看似隨機。如果我自己重新運行任何失敗的測試,它會通過。x單元測試死鎖

我應該怎麼做才能防止這種情況?是否有一個選項可以一次又一次地運行測試,而不是一次全部運行?

這裏(NB我的Visual Studio 2015年中運行了我的ASP.Net MVC 5控制器API方法測試)是我偶爾的失敗測試中的一個例子:

[Fact] 
private void TestREAD() 
{ 
    Linq2SQLTestHelpers.SQLCommands.AddCollections(TestCollections.Select(collection => Convert.Collection2DB(collection)).ToList(), TestSettings.LocalConnectionString); 
    foreach (var testCollection in TestCollections) 
    { 
     var testCollectionFromDB = CollectionsController.Get(testCollection.Id); 
     Assert.Equal(testCollection.Description, testCollectionFromDB.Description); 
     Assert.Equal(testCollection.Id, testCollectionFromDB.Id); 
     Assert.Equal(testCollection.IsPublic, testCollectionFromDB.IsPublic); 
     Assert.Equal(testCollection.LayoutSettings, testCollectionFromDB.LayoutSettings); 
     Assert.Equal(testCollection.Name, testCollectionFromDB.Name); 
     Assert.Equal(testCollection.UserId, testCollectionFromDB.UserId); 
    } 
} 

有兩種方法的測試呼叫,這裏的控制器方法:

[HttpGet("{id}")] 
public Collection Get(Guid id) 
{ 
    var sql = @"SELECT * FROM Collections WHERE id = @id"; 
    using (var connection = new SqlConnection(ConnectionString)) 
    { 
     var collection = connection.Query<Collection>(sql, new { id = id }).First(); 
     return collection; 
    } 
} 

和這裏的輔助方法:

public static void AddCollections(List<Collection> collections, string connectionString) 
{ 
    using (var db = new DataClassesDataContext(connectionString)) 
    { 
     db.Collections.InsertAllOnSubmit(collections); 
     db.SubmitChanges(); 
    } 
} 

(請注意,我在控制器方法中使用Dapper作爲微型ORM,因此爲避免可能在測試中重複出現錯誤,我使用LINQ to SQL代替測試中的設置和清理測試數據)。

單元測試的類的構造函數和Dispose方法中還有數據庫調用。如果需要,我可以將它們添加到帖子中。

+1

您可能要分享您正在編寫的測試類型 - 對「異步」/「任務」管理等的一些洞察。現在你可以做任何事情,顯然有一些人正在取得成功,我們只需要弄清楚你的背景下有什麼泄露/鎖定...... –

+0

完成了,這足夠嗎? – dumbledad

+1

嗯 - 看起來不像那些可以歸咎於xUnit那麼多。你是否在打斷連接[及其相關的鎖]? –

回答

1

好的,看起來像是在您的應用程序中存在死鎖的簡單香草案,並且需要處理該問題 - 您在應用程序方面的計劃是什麼?

測試和他們的數據綁定可能會陷入同樣的​​事情。 xUnit沒有任何解決這個問題的方法,我強烈主張不應該這樣做。

所以在測試和應用程序中,都需要失敗/重試管理。

對於一個網絡應用程序,你有一個消防他們的鯨魚的照片,讓他們再試一次模式,但最終你想要一個真正的解決方案。

對於一項測試,你不需要鯨魚,並且一定要處理它,即不是脆弱的。

我會使用保利包裹在任何應用程序或測試中的任何重試裝飾的重大失敗 - 你的練習是找出你的上下文中的顯着的失敗。


在正常情況下,一個數據庫同時運行一個讀寫器應該不會死鎖。分析它發生的原因是在數據庫方面進行分析。如果有的話,那邊的工具也可能很快顯示給你。你的整個系統被測試的某些方面會導致競爭性的工作。

(顯然您的片段是不完整的,因爲是CollectionsController.Get(testCollection.Id)和事實之間的脫節控制器方法不是static - 這次討論的點不應該是下來在這一水平IMO雖然)

+0

在控制器的構造函數中很少有初始化,我只是傳入一個連接字符串,作爲IOptions打包以進行依賴注入。測試看起來是隨機失敗的,所以它們都「容易出現嚴重故障」。我不確定用什麼工具來分析數據庫方面的僵局,但我會進行調查。謝謝。 – dumbledad

+0

@dumbledad SQL事件探查器可以顯示它們。 Re「測試看起來是隨機失敗的,」有一點需要弄清楚的是它的測試夾具設置或控制器中導致問題的東西 - 也就是說如果它是實際的控制器,那麼你可以把它看作是一個錯誤控制器需要通過在那裏有一些受限制的重試來修復 –

+1

Profiler顯示了一個死鎖,它似乎來自我的INSTEAD OF DELETE觸發器,它將級聯刪除。所以我認爲你是正確的,這是一個僵局,可能會讓我在實​​時代碼中咬人,而不僅僅是一個測試。我結束了以下的建議[這裏](http://stackoverflow.com/a/35361855/575530)並刪除觸發器並將其重寫爲存儲過程,現在我的測試都運行沒有錯誤。 – dumbledad