今天我遇到了一個奇怪的問題 - 我正在圍繞SIM對象編寫單元測試。它斷言當SIM對象被更新並且PIN嘗試保持改變時,它將調用特定的方法。該測試是這樣的:Moq在構造函數中使用延遲加載
[Test]
public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining()
{
var info = new SimPinInfo {PinAttemptsRemaining = 10};
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
sim.Object.UpdateSimInfo(info);
sim.Verify(s => s.FireOnPinAttemptsRemaining(), Times.Once());
}
所以模擬SIM對象與10次PIN嘗試其餘創建。在傳遞給UpdateSimInfo()
方法之前,SimPinInfo
對象將PinAttemptsRemaining
值減爲2。
SIM構造(修剪清晰度):
internal Sim(SimPinInfo info) : this()
{
_pinAttemptsRemaining = info.PinAttemptsRemaining;
_pukAttemptsRemaining = info.PukAttemptsRemaining;
......
}
而且UpdateSimInfo()
法(修整):
internal void UpdateSimInfo(SimPinInfo info)
{
lock(_locker)
{
if (_pinAttemptsRemaining != info.PinAttemptsRemaining)
{
Log("PinAttemptsRemaining changed");
_pinAttemptsRemaining = info.PinAttemptsRemaining;
FireOnPinAttemptsRemaining();
}
.....
}
}
一個非常簡單的測試 - 會發生什麼是上面的if語句爲真(引腳嘗試剩餘已更改),因此OnPinAttemptsRemaining
事件將被觸發。然而,測試失敗了(儘管不是所有的時間 - 當我慢慢地通過代碼時它通過了!)。什麼是發生在if語句是假的 - 既_pinAttemptsRemaining
和info.PinAttemptsRemaining
是2.看來,預計當SIM模擬不實際創建 - 當info.PinAttemptsRemaining
是10
爲了證明這一點,我添加了一個評論:
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
Console.WriteLine("SIM's pin attempts = " + sim.Object.PinAttemptsRemaining);
我也在SIM對象的構造函數中放置了一個斷點。跳過Console.WriteLine
行時,跳過了斷點,而不是new Mock...
行。所以這個對象直到需要時纔會被創建。
我相信這被稱爲延遲加載或懶惰評估。
有這種行爲的各種解決方法 - 我結束了創建一個新的SimPinInfo
對象傳遞到UpdateSimInfo()
。
以前有沒有人遇到過這種行爲?我找不到任何參考。
謝謝史蒂夫。我開始使用監視器等實際上等待不同線程上的事件的單元測試。下一步看起來像你的代碼,它運行良好,我終於在我的問題中使用了模擬代碼。我可能會回到你的風格,但你可以解釋「替代依賴/替代代碼」的評論。乾杯。 – barry
可能是最簡單的解釋方法。假設你有一個包裝數據訪問的服務。 DataService的。它直接與您的數據庫進行通話。您有其他使用DataService檢索和保存信息的代碼。現在您要測試一些需要從DataService獲取數據的代碼。 Mock允許您通過嘲笑數據服務來獨立於數據服務來測試代碼。例如,我將爲數據服務提供稱爲IDataService的合同接口。通過使用Mock,您可以設置預期的場景,而不需要「真正的」數據連接。 –