2015-11-10 41 views
4

我創建單元測試來協助構建一些代碼,它將接受來自我的控制器的入站請求並對其進行排隊(如果需要)。單元測試和多個異步任務

在我的單元測試中,我想讓兩行代碼在相同的時間幾乎同時觸發,儘管在兩次調用之間有2秒的延遲。這允許我的邏輯的第一個分支被觸發,然後在第二個調用中,因爲已經看到傳遞的數據,所以使用邏輯的替代分支。

我走近了,但感覺凌亂。我正在使用下面的代碼,它會立即傳遞我的第一個呼叫,並轉到後續的代碼行。

Task.Factory.StartNew(() => stubbedQueueHandler.QueueProcessor(setupModel)); 

Thread.Sleep(2000); 
//second call 
stubbedQueueHandler.QueueProcessor(setupModel); 

await Task.Delay(10000); 

但是,單元測試在第一次調用完成之前結束,這反過來又殺死了進程。允許第一個電話完成的唯一方法是放置一個await Task.Delay()線路,這個技巧。

我明白了它爲什麼這麼做,因爲我已經有效地將呼叫轉移了,而沒有期望回覆。我不想開始使用任務延遲,並且我相信這只是我缺乏理解,這是異步編程的問題:o)。

回答

4

你需要的是捕捉揭開序幕QueueProcessor並等待它調用的第二次存根後Task

public async Task FooTestAsync() 
{ 
    var task = Task.Run(() => stubbedQueueHandler.QueueProcessor(setupModel)); 
    await Task.Delay(2000); 

    stubbedQueueHandler.QueueProcessor(setupModel); 
    await task; 
} 

這樣,可以確保操作的完成操作完成之前,因爲QueueProcessor將同步阻塞直到其操作完成。

+0

完美無瑕!謝謝! – Sulphy

+0

@Sulphy歡迎你。 –

3

您需要避免在您的異步代碼中使用Thread.Sleep()。

參考Figure 5 The 「Async Way」 of Doing Things

To Do This        Instead of This   Use This 
Retrieve the result of a background task Task.Wait or Task.Result await 
Wait for any task to complete    Task.WaitAny    await Task.WhenAny 
Retrieve the results of multiple tasks Task.WaitAll    await Task.WhenAll 
Wait a period of time      Thread.Sleep    await Task.Delay 

你應該避免混合異步和阻塞的代碼。混合異步和阻止代碼可能導致死鎖,更復雜的錯誤處理和意外阻塞上下文線程。

+1

好點,我開始接觸的一個壞習慣,將會爲未來扼殺! :o) – Sulphy

+0

這是一個評論,而不是OPs問題的答案。 –