2009-07-23 250 views
20

我在.NET平臺上使用Xunit和NMock。 我正在測試一個方法是異步的表示模型。 該方法創建一個異步任務並執行它,以便該方法立即返回,並且需要檢查的狀態尚未準備好。有沒有一種方法來單元測試異步方法?

我可以在不修改SUT的情況下設置標誌,但這意味着我必須在while循環中檢查標誌,例如可能超時。

我有什麼選擇?

+0

.NET不具備條件變量? – jrockway 2009-07-23 21:50:29

+0

你想要測試什麼? – 2009-07-23 22:00:08

+0

有複雜的解決方案,但如果它只是一個測試,那麼循環/超時/標誌選項沒有任何問題。 – Ray 2009-07-24 08:19:10

回答

19

您的對象是否具有異步方法完成的任何種類的信號,例如事件?如果是這樣的話,你可以用下面的辦法:

[Test] 
public void CanTestAsync() 
{ 
    MyObject instance = new MyObject() 
    AutoResetEvent waitHandle = new AutoResetEvent(false); 
    // create and attach event handler for the "Finished" event 
    EventHandler eventHandler = delegate(object sender, EventArgs e) 
    { 
     waitHandle.Set(); // signal that the finished event was raised 
    } 
    instance.AsyncMethodFinished += eventHandler; 

    // call the async method 
    instance.CallAsyncMethod(); 

    // Wait until the event handler is invoked 
    if (!waitHandle.WaitOne(5000, false)) 
    { 
     Assert.Fail("Test timed out."); 
    } 
    instance.AsyncMethodFinished -= eventHandler;  
    Assert.AreEqual("expected", instance.ValueToCheck); 
} 
4

我的首選方法是模擬並注入實際的線程機制,以便在測試中它不是異步的。有些時候這是不可能的(如果方法的線程是框架的一部分,或者不在你的控制之下)。

如果你不能控制線程創建,那麼等待線程以某種方式完成,或者是一個while循環,或者只是一個定時的等待,無論線程應該佔用多長時間,並且如果狀態爲不在那裏,因爲反正花了太長時間。

46

只是覺得你可能想要在這方面的更新,因爲#1答案實際上是建議一個較舊的模式來解決這個問題。

在.net 4.5 + xUnit 1.9或更高版本中,您可以簡單地返回一個Task,並可以使用測試中的async關鍵字讓xunit等待測試異步完成。

請參閱這篇文章xUnit.net 1.9

[Fact] 
public async Task MyAsyncUnitTest() 
{  
    // ... setup code here ...  
    var result = await CallMyAsyncApi(...);  
    // ... assertions here ... 
} 
相關問題