我有一個正在測驗的物件,其方法稱為void Print(string msg).
該物件多次呼叫該方法并傳遞不同的訊息。
例如...
海峽前進的用法:
public interface IMyPrinter
{
void Print(string msg);
}
public class Printer : IMyPrinter
{
public void Print(string msg)
{
// print to console
}
}
public class MyObject
{
public IMyPrinter Printer { get; set; }
public void foo()
{
for (var count = 0; count < 4; count )
{
Printer.Print($"abc_{count}");
}
}
}
當我想測驗foo方法時,如何設定Mock物件以捕獲不同的Print方法呼叫?
我試過:
var printerMock = new Mock<IMyPrinter>(MockBehavior.Loose);
for (var count = 0; count < 4; count )
{
printerMock.Setup(_ => _.Print($"abc_{count}");
}
var underTest = new MyObject();
underTest.Printer = printerMock.Object;
underTest.foo();
printerMock.VerifyAll();
但這當然只會使最后一次設定有效(當count= 3 時)。如何才能做到這一點?
uj5u.com熱心網友回復:
但這當然只會使最后一次設定有效(當計數 = 3 時)。
實際上這不是真的,如果您仔細查看測驗輸出,您會發現它包含 4 個值為4! 的呼叫:
IMyPrinter _ => _.Print("abc_4")
IMyPrinter _ => _.Print("abc_4")
IMyPrinter _ => _.Print("abc_4")
IMyPrinter _ => _.Print("abc_4")
這是count回圈結束后的值。由于您使用的是 lambda 運算式,因此您的count變數被閉包4捕獲并捕獲了最后一個值。當回圈很久以前完成時,稍后在代碼中評估 lambda 運算式時,僅使用此值。您需要創建一個臨時變數并捕獲其中的索引。您的測驗將運行綠色:
var printerMock = new Mock<IMyPrinter>(MockBehavior.Loose);
for (var count = 0; count < 4; count )
{
int i = count; // <-- this is the main change
printerMock.Setup(_ => _.Print($"abc_{i}")); // <-- use "i" in lambda
}
var underTest = new MyObject();
underTest.Printer = printerMock.Object;
underTest.foo();
printerMock.VerifyAll();
編輯:
為了進一步閱讀關于閉包的內容,我推薦了 Jon Skeet 的這篇文章
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/335944.html
