为不同的输入和输出设置模拟对象方法,警告:访问修改的闭包
Setup Mock object method for varying inputs and outputs, warns: access to modified closure
我想设置一个模拟对象,其方法应该 return 每个输入都不同。当我尝试类似下面给出的代码时,我收到了关于访问修改后的闭包的警告(即访问 i
)。如何将模拟对象的 FooMethod(i)
正确设置为 return i*3
?
var ret = new Mock<FooClass>();
for(var i = 0; i < 10; i++){
var bar = i*3;
ret.Setup(x => x.FooMethod(i)).Returns(bar);
}
Olivier 已经在评论中说过了。由于 for
变量的闭包语义,Moq 在您的代码中看到的实际上是:
ret.Setup(x => x.FooMethod(10)).Returns(0);
ret.Setup(x => x.FooMethod(10)).Returns(3);
ret.Setup(x => x.FooMethod(10)).Returns(6);
ret.Setup(x => x.FooMethod(10)).Returns(9);
ret.Setup(x => x.FooMethod(10)).Returns(12);
ret.Setup(x => x.FooMethod(10)).Returns(15);
ret.Setup(x => x.FooMethod(10)).Returns(18);
ret.Setup(x => x.FooMethod(10)).Returns(21);
ret.Setup(x => x.FooMethod(10)).Returns(24);
ret.Setup(x => x.FooMethod(10)).Returns(27);
这当然不是你想要的。 (Moq 将只设置为值 10
,并且它将使用最新的 Setup
,因此 return 27
。)
不要关闭(捕获)for
变量。一种修复方法是:
for (var i = 0; i < 10; i++) {
var iCopy = i;
ret.Setup(x => x.FooMethod(iCopy)).Returns(3 * iCopy);
}
在较新版本的 C# 中,foreach
循环有所不同。因此,这有效:
foreach (var i in Enumerable.Range(0, 10)) {
ret.Setup(x => x.FooMethod(i)).Returns(3 * i);
}
Moq 提供了另一种不需要循环的方法。是这样的:
ret.Setup(x => x.FooMethod(It.IsAny<int>())).Returns((int i) => 3 * i);
当然这是为全部i
设置的。如果你不想这样,你可以改成:
ret.Setup(x => x.FooMethod(It.Is((int i) => 0 <= i && i < 10))).Returns((int i) => 3 * i);
我想设置一个模拟对象,其方法应该 return 每个输入都不同。当我尝试类似下面给出的代码时,我收到了关于访问修改后的闭包的警告(即访问 i
)。如何将模拟对象的 FooMethod(i)
正确设置为 return i*3
?
var ret = new Mock<FooClass>();
for(var i = 0; i < 10; i++){
var bar = i*3;
ret.Setup(x => x.FooMethod(i)).Returns(bar);
}
Olivier 已经在评论中说过了。由于 for
变量的闭包语义,Moq 在您的代码中看到的实际上是:
ret.Setup(x => x.FooMethod(10)).Returns(0);
ret.Setup(x => x.FooMethod(10)).Returns(3);
ret.Setup(x => x.FooMethod(10)).Returns(6);
ret.Setup(x => x.FooMethod(10)).Returns(9);
ret.Setup(x => x.FooMethod(10)).Returns(12);
ret.Setup(x => x.FooMethod(10)).Returns(15);
ret.Setup(x => x.FooMethod(10)).Returns(18);
ret.Setup(x => x.FooMethod(10)).Returns(21);
ret.Setup(x => x.FooMethod(10)).Returns(24);
ret.Setup(x => x.FooMethod(10)).Returns(27);
这当然不是你想要的。 (Moq 将只设置为值 10
,并且它将使用最新的 Setup
,因此 return 27
。)
不要关闭(捕获)for
变量。一种修复方法是:
for (var i = 0; i < 10; i++) {
var iCopy = i;
ret.Setup(x => x.FooMethod(iCopy)).Returns(3 * iCopy);
}
在较新版本的 C# 中,foreach
循环有所不同。因此,这有效:
foreach (var i in Enumerable.Range(0, 10)) {
ret.Setup(x => x.FooMethod(i)).Returns(3 * i);
}
Moq 提供了另一种不需要循环的方法。是这样的:
ret.Setup(x => x.FooMethod(It.IsAny<int>())).Returns((int i) => 3 * i);
当然这是为全部i
设置的。如果你不想这样,你可以改成:
ret.Setup(x => x.FooMethod(It.Is((int i) => 0 <= i && i < 10))).Returns((int i) => 3 * i);