我在测试中设置我的一个模拟有一些问题,最终会多次调用设置,但是参数不同,所以:
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>());
}
Run Code Online (Sandbox Code Playgroud)
所以,上面的方法不起作用.似乎只有最后一次迭代才会被模拟"记住".如何在一个模拟上设置许多设置,就像我打算在上面做的那样?
当您在lambda表达式中使用外部变量时 - 它会被此lambda表达式"捕获"并延长其生命周期.在这个例子中,lambda表达式是你传递给Setup调用的,而外部变量是i循环变量.它的生命周期应该扩展到for循环之外,因为你不知道Setup该变量是做什么的- 它可能在for循环之后长时间使用它甚至包含函数结束.因此,编译器将此局部变量替换为编译器生成的类中的字段.现在,您Setup在循环中传递的所有lambd都引用完全相同的位置 - 编译器生成的类的字段,其中i替换了变量.
当你调用mocked函数时 - Moq将比较你传递的参数和可用的设置.但由于所有设置都引用了相同的位置 - 它们都引用了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>());
}
Run Code Online (Sandbox Code Playgroud)
它也被捕获并且它的生命周期被扩展,但是这次每次循环迭代都有它自己的变量,所以它是编译器生成的类的自己的实例,现在所有的Setuplambda都使用不同的值.