2013-06-11 37 views
23

有什么区别我正在使用Moq并希望创建生成器类以创建我的模拟与预设合理的默认值,可以根据需要在测试设置期间被覆盖。我采取的方法使用扩展方法,其中我传递输入参数值和期望的输出。在这样做的过程中,我看到不同的行为在我看来是语义上等同的代码:直接在设置中传递It.IsAny(),或在设置中间接传递It.IsAny()的值。例如:通过It.IsAny <int>()和它的值It.IsAny <int>()对方法设置

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 

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

回答

33

It.IsAny只允许Moq匹配在Setup构造中使用的方法调用的未来调用。当调用Setup时,Moq只是将方法调用添加到已设置的方法调用的缓存中。请注意,示例中Setup的参数的类型为Expression<Func<IFoo, bool>>。由于您传递的是Expression,因此不会调用实际的方法调用,并且Moq能够遍历表达式以确定方法调用的哪些参数是显式的,哪些参数是It.IsAny参数。它使用此功能来确定运行时将来的方法调用是否与已经建立的方法调用之一相匹配。

为了让这个方法Bar可以接受参数It.IsAny<int>(),有必要使It.IsAny<int>()返回一个int(因为这是Bar参数的类型)。一般而言,退货类型It.IsAny<T>必须为T。必须选择任意值T。最自然的选择是default(T),它适用于参考类型和值类型。 (详细了解默认关键字here)。在你的情况下,这是default(int),这是0

所以,当你真正评估It.IsAny<int>()立即返回的0值。但是,当你在一个Expression使用It.IsAny<int>()(作为参数传递给Setup方法),那么方法调用的树形结构保存和起订量能够满足未来的方法调用由Expression封装的方法调用。

所以,虽然你不能保持It.IsAny<int>()以任何有意义的方式可变,可以保持整个Expression在一个变量:

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

最后,我只是想提醒你,起订量是开源的。源可用here。我发现拥有该源代码非常有价值,这样我可以点击并浏览代码和单元测试。

+1

非常好的解释,本。正如你所描述的那样,我怀疑问题在于表达式评估,而不是It.IsAny的返回值()。我在ILSpy中查看了反射源,并可以看到它。但是无法让我的脑袋围绕它如何解决问题。 再次感谢您的解释。 –

+0

感谢您为我清理巫术!我试图说“var anyFooParam = It.IsAny (); var anyBarParam = It.IsAny ();”看看它是否会让我的测试更具可读性,例如:.Setup(mock => mock.method(anyFooParam,anyBarParam))。Returns(something!) –

1

It.IsAny<int>()具有返回为int类型,并返回0,使你的第二个设置等同于:

mock.Setup(x => x.Bar2(0)).Returns(true); 

我没有检查MOQ代码,但我敢肯定,当计算表达式在设置方法中,它考虑到参数实际上是It.IsAny与正常数字。

,如果您直接在辅助方法创建的设置你都关闭好,而不是通过It.IsAny。

相关问题