當使用Moq來模擬稱爲大量次數的依賴項時,我遇到了一個障礙。當我撥打Verify
時,Moq需要很長時間(幾分鐘)才能響應,有時會以NullReferenceException
崩潰(我想這是可以理解的,因爲Moq
必須積累起來才能從「冷啓動」開始執行Verify
「)。Moq在大量調用後很難驗證依賴關係
所以我的問題是,是否有另一種策略,我可以使用Moq來做到這一點,或者我應該回到這個相當不尋常的情況手工製作的存根。具體來說,有沒有辦法先告訴Moq,我只想驗證特定過濾器的參數,並忽略所有其他值?
以下兩種方法都不令人滿意。
鑑於CUT和DEP:
public interface ISomeInterface
{
void SomeMethod(int someValue);
}
public class ClassUnderTest
{
private readonly ISomeInterface _dep;
public ClassUnderTest(ISomeInterface dep)
{
_dep = dep;
}
public void DoWork()
{
for (var i = 0; i < 1000000; i++) // Large number of calls to dep
{
_dep.SomeMethod(i);
}
}
}
Moq的策略1 - 驗證
var mockSF = new Mock<ISomeInterface>();
var cut = new ClassUnderTest(mockSF.Object);
cut.DoWork();
mockSF.Verify(mockInt => mockInt.SomeMethod(It.Is<int>(i => i == 12345)),
Times.Once());
mockSF.Verify(mockInt => mockInt.SomeMethod(It.Is<int>(i => i == -1)),
Times.Never());
Moq的策略2 - 回調
var mockSF = new Mock<ISomeInterface>();
var cut = new ClassUnderTest(mockSF.Object);
bool isGoodValueAlreadyUsed = false;
mockSF.Setup(mockInt => mockInt.SomeMethod(It.Is<int>(i => i == 12345)))
.Callback(() =>
{
if (isGoodValueAlreadyUsed)
{
throw new InvalidOperationException();
}
isGoodValueAlreadyUsed = true;
});
mockSF.Setup(mockInt => mockInt.SomeMethod(It.Is<int>(i => i == -1)))
.Callback(() =>
{ throw new InvalidOperationException(); });
cut.DoWork();
Assert.IsTrue(isGoodValueAlreadyUsed);
+1 - 你說得很好。實際上,生成,投影和存儲方面的問題是分開的(CUT是NoSQL ETL過程的一部分),但我很懶惰,試圖在單個單元測試中做太多事情。我將通過對較小數據集的單獨測試驗證投影和存儲依賴性的使用情況,並檢查CUT在更大集合上使用生成器的性能。不過,我仍然有興趣瞭解Moq是否可以選擇配置爲僅跟蹤特定參數值。 – StuartLC
Moq並非設計用於大量可驗證的調用。在一小組調用中,任何組合設置都可以輕鬆完成。閱讀我編輯的簡化設置,瞭解您提供的示例。請注意,它在大型設備上仍然非常慢,但它可以爲您提供可能使用的不同類型設置的想法。 –