Moq - 如何在循环中使用不同的参数调用相同的设置

时间:2018-02-13 08:50:11

标签: c# testing moq

我在测试中设置了一个模拟问题,最终会多次调用设置,但参数不同,所以:

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;通过模拟。如何在一个模拟上设置许多设置,就像我打算在上面做的那样?

2 个答案:

答案 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以更好地了解如何使用模拟库。