是什么传递It.IsAny℃之间的差; INT&GT)和It.IsAny&所述的值(;一种方法设置(); INT&GT [英] What is the difference between passing It.IsAny<int>() and the value of It.IsAny<int>() to a method setup

查看:71
本文介绍了是什么传递It.IsAny℃之间的差; INT&GT)和It.IsAny&所述的值(;一种方法设置(); INT&GT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用起订量,并希望创建生成器类来创建我的,可以测试在安装过程中根据需要重写preSET合理的默认值嘲笑。我采取的方法使用中,我通过输入参数值和预期输出扩展方法。这样做,我在看到不同的行为是什么,在我看来是语义等价的code:通过It.IsAny()直接在安装VS传递It.IsAny的值()间接的设置。例如:

I'm using Moq and want to create builder classes to create my mocks with preset reasonable defaults that can be overridden during test setup as needed. The approach I took uses extension methods in which I pass input parameter values and expected output. In doing so, I'm seeing different behavior in what seems to me to be semantically equivalent code: passing It.IsAny() directly in a setup vs passing the value of It.IsAny() indirectly in a setup. Example:

public interface IFoo
{
    bool Bar(int value);
    bool Bar2(int value);
}
public class Foo : IFoo
{
    public bool Bar(int value) { return false; }
    public bool Bar2(int value) { return false; }
}

var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar(It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.Bar(123));                    // Succeeds

var myValue = It.IsAny<int>();
mock.Setup(x => x.Bar2(myValue)).Returns(true);
Assert.IsTrue(mock.Object.Bar2(123));                   // Fails

两个调用是等价的(对我来说),但调用失败条2断言。这是为什么?

Both calls are equivalent (to me), yet the call to Bar2 fails assertion. Why is this?

推荐答案

It.IsAny 只允许起订量匹配方法的将来调用,如果<$ C内使用电话$ C>设置构造。当设置被称为起订量只是增加了方法调用其业已建立的方法调用缓存。请注意,您的示例参数设置已键入防爆pression&LT; Func键&LT;的IFoo,布尔&GT;&GT; 。因为你是传递一个防爆pression ,实际的方法调用不调用,起订量已遍历前pression找出哪些参数的能力方法调用的是明确的,哪些是 It.IsAny 参数。它使用这种能力,以确定是否在运行时以后的方法调用相匹配的已建立的方法调用中的一个。

It.IsAny only allows Moq to match future invocations of method calls if used within the Setup construct. When Setup is called Moq just adds the method call to its cache of already-set-up method calls. Note that the argument to Setup in your example has type Expression<Func<IFoo, bool>>. Since you are passing in an Expression, the actual method call is not invoked and Moq has the ability to traverse the expression to figure out which parameters of the method call were explicit, and which are It.IsAny arguments. It uses this ability to determine if a future method call at runtime matches one of the already-set-up method calls.

为了让这个方法酒吧可以接受的说法 It.IsAny&LT; INT&GT;() ,有必要让 It.IsAny&LT; INT&GT;()返回 INT (因为这是类型酒吧的参数)。一般情况下, It.IsAny&LT的返回类型; T&GT; 必须 T T 的任意值必须选择。最自然的选择是默认(T),它适用于引用类型和值类型。 (了解更多关于默认的关键字这里)。在你的情况,那就是默认(INT),这是 0

In order to make it so that the method Bar can accept argument It.IsAny<int>(), it is necessary to make It.IsAny<int>() return an int (since that is the type of the parameter of Bar). In general, the return type of It.IsAny<T> must be T. An arbitrary value of T must be chosen. The most natural choice is default(T), which works for reference types and value types. (Read more about the default keyword here). In your case, that is default(int), which is 0.

所以,当你真正评估 It.IsAny&LT; INT&GT;() 0 的值被立即返回。但是,当您使用 It.IsAny&LT; INT&GT;()防爆pression (如参数传递给设置方法),那么方法调用的树状结构是preserved和起订量能够满足未来的方法调用由<$ C封装方法调用$ C>防爆pression 。

So when you actually evaluate It.IsAny<int>() the value of 0 is immediately returned. However, when you use It.IsAny<int>() in an Expression (as in the argument to the Setup method), then the tree structure of the method call is preserved and Moq can match future method invocations to the method call encapsulated by the Expression.

所以,虽然你不能保持 It.IsAny&LT; INT&GT;()以任何有意义的方式可变,可以保持整个防爆pression 在一个变量:

So, although you cannot keep It.IsAny<int>() as a variable in any meaningful way, you can keep the entire Expression in a variable:

Expression<Func<IFoo, bool>> myExpr = x => x.Bar2(It.IsAny<int>());
mock.Setup(myExpr).Returns(true);
Assert.IsTrue(mock.Object.Bar2(123));  

最后,我只是想提醒你,起订量是开源的。提供源代码这里。我发现有价值的有源$ C ​​$ C,这样我可以按一下周围,探索code和单元测试。

Finally, I just want to remind you that Moq is open source. The source is available here. I find it valuable to have that source code so that I can click around and explore the code and the unit tests.

这篇关于是什么传递It.IsAny℃之间的差; INT&GT)和It.IsAny&所述的值(;一种方法设置(); INT&GT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆