我在测试中设置了一个模拟问题,最终会多次调用设置,但参数不同,所以:
var testMock = new Mock<SomeClass>(MockBehavior.Strict);
for (int i = 30000; i <= 300000; i+=10000)
{
testMock.Setup(x => x.MethodA(SomeStaticClass.GetIt(varA, varB, i), It.IsAny<int>()))
.Returns(new List<SomeClass>());
}
所以,上述方法并不奏效。似乎只有最后一次迭代才会被记住&#34;通过模拟。如何在一个模拟上设置许多设置,就像我打算在上面做的那样?
答案 0 :(得分:5)
当您在lambda表达式中使用外部变量时 - 它变为&#34;捕获&#34;通过这个lambda表达式并延长其寿命。在此示例中,lambda表达式是您传递给Setup
调用的,而外部变量是i
循环变量。它的生命周期应该延伸到for
循环之外,因为你不知道Setup
将对该变量做什么 - 它可能会在{{1}之后使用它很长一段时间循环甚至包含函数结束。因此,编译器将此局部变量替换为编译器生成的类中的字段。现在,您在循环中传递给for
的所有lambd都引用了完全相同的位置 - 编译器生成的类的字段,其中Setup
变量被替换。
当您调用mocked函数时 - Moq会将您传递的参数与可用设置进行比较。但由于所有设置都引用了相同的位置 - 它们都引用了i
的最后一个值,它在循环结束时有。
将循环变量复制到另一个变量时:
i
它也被捕获并且它的生命周期被扩展,但是这次每次循环迭代都有它自己的变量,所以它自己的编译器生成的类的实例,现在所有for (int i = 30000; i <= 300000; i+=10000)
{
var tmp = i;
testMock.Setup(x => x.MethodA(SomeStaticClass.GetIt(varA, varB, tmp), It.IsAny<int>()))
.Returns(new List<SomeClass>());
}
lambdas使用不同的值。
答案 1 :(得分:1)
这可以在没有循环的情况下通过使用git update-index --skip-worktree
参数匹配器来完成静态类返回的任何值。
因此,让我们假设模拟的It.*
期望值介于300到3000之间。然后MethodA
会设置模拟以期望并处理该范围
It.IsInRange
另外,请参考Moq Quickstart以更好地了解如何使用模拟库。