2012-07-26 53 views
1

我遇到過當使用NSubstitute模擬具有輸出參數的方法時的情況。 我不知道如何最好地解釋它的文本,所以我會用一些人爲的例子和測試用例...NSubstitute在循環中多次調用時返回意外值

在這個人爲的例子,我將使用一個IDictionary<string, string>的NSubstitute模擬。

private static IDictionary<string, string> GetSubstituteDictionary() 
{ 
    IDictionary<string, string> dict = Substitute.For<IDictionary<string, string>>(); 

    string s; 
    dict.TryGetValue("key", out s).Returns(ci => { ci[1] = "value"; return true; }); 

    return dict; 
} 

現在,當我以簡單的方式使用該模擬對象,它返回預期:

[Test] 
public void ExampleOne() 
{ 
    var dict = GetSubstituteDictionary(); 

    string value; 
    bool result = dict.TryGetValue("key", out value); 

    Assert.That(result, Is.True); // this assert passes. 
    Assert.That(value, Is.EqualTo("value")); // this assert passes. 
} 

然而,當我打電話相同的代碼在for循環中,我得到一些意想不到的行爲:

[Test] 
public void ExampleTwo() 
{ 
    var dict = GetSubstituteDictionary(); 

    for (int i = 0; i < 2; i++) 
    { 
     string value; 
     bool result = dict.TryGetValue("key", out value); 

     Assert.That(result, Is.True); // this assert FAILS - unexpected! 
     Assert.That(value, Is.EqualTo("value")); // this assert still passes. 
    } 
} 

特別地,Assert.That(result, Is.True);斷言傳遞循環的第一次迭代,但是未能在第二(和任何後續)迭代。

但是,如果我將string value;行修改爲string value = null;,則斷言將通過所有迭代。

這是什麼導致這種異常?這是由於我缺少一些C#for循環的語義,或者它是NSubstitute庫的問題嗎?

回答

3

原因是value循環中的變量發生變化(通過輸出參數設置),因此它不再匹配您剔除的調用。

您可以嘗試使用.ReturnsForAnyArgs(),但您需要檢查存根中的密鑰,而不是通過參數匹配器。

+0

謝謝,這是有道理的時候'價值'聲明在循環之外;即使在循環體中聲明瞭'value',這樣的情況也是如此,因此僅在循環體內的範圍內?我會認爲循環的每次迭代都會有自己的「'值」。 – MatthewKing 2012-07-26 04:08:23

+1

我相信編譯器會認識到它可以重用'value'變量。我的IL閱讀技能不足以說明問題,但是我通過調試器運行它,在下一次循環迭代中,「value」仍然是「值」。如果您將該行更改爲'string value = null;'測試通過正常。 – 2012-07-26 07:39:25