2017-04-21 95 views
1

我有一個方法:MustHaveHappened斷言總是失敗的一個單獨的線程運行的異步方法(Task.Run)

public class MyClass 
{ 
    public ILogger _logger; 

    public async void TestLogMethod(string msg) 
    { 
     await Task.Run(async()=> await _logger.Log(msg)); 
    } 
} 

和測試用例:

[Test] 
public async Task TestLogMethod_LogMessage_Test() 
{ 
    var fakeLogger = A.Fake<ILogger>(); 
    var testClass = new MyClass(); 
    testClass._logger = fakeLogger; 

    testClass.TestLogMethod("Test Message"); 

    A.CallTo(() => fakeLogger.Log(A<string>._)).MustHaveHappened(); 
} 

MustHaveHappened斷言總是失敗說

以下呼叫的聲明失敗:
MyClass.TestLogMethod <System.Object>(<忽略>)
預計至少會發現一次,但沒有對假對象進行調用。

很明顯,_logger.Log()被調用,但爲什麼在這裏斷言總是失敗?

+1

你可以先解釋爲什麼你有一個'async void'方法等待一個新的任務,它等待着另一個任務? –

+0

還應該考慮[顯式依賴關係原則](http://deviq.com/explicit-dependencies-principle/) – Nkosi

+2

在我關於[異步最佳實踐]的文章(https://msdn.microsoft.com/en-us /magazine/jj991977.aspx),我提到了幾個避免使用'async void'方法的原因;其中之一是「異步無效方法很難測試」。 –

回答

5

您並未等待TestLogMethod的完成,因此您在發生這種情況之前驗證期望值。將在線程池上計劃Task,然後該方法將立即返回。這就是爲什麼你應該使用avoid async void的方法。

更改方法返回Task所以你有東西await。您還可以去除大部分的asyncawait雙這裏因爲他們是多餘的:

public Task TestLogMethod(string msg) 
{ 
    return Task.Run(() => _logger.Log(msg)); 
} 

然後await,在您的測試:

await testClass.TestLogMethod("Test Message"); 

,然後通過時間的驗證發生在通話到ILogger.Log將會發生。

相關問題