如何使用It.IsAny作为参数?

时间:2019-02-14 08:14:46

标签: c# moq

我有一个测试类,它调用MyClass的模拟,我以前SetupDoStuffADoStuffB

我尝试将多个Verify调用包装在一个方法中,如下所示:

void VerifyMany(int input)
{
    _myClassMock.Verify(ic => ic.DoStuffA(input), Times.Once());
    _myClassMock.Verify(ic => ic.DoStuffB(input), Times.Once());
}

如果我使用It.IsAny<int>()作为输入来调用我的方法-VerifyMany(It.IsAny<int>())-我的测试没有通过,但是如果我直接使用It.IsAny直接调用Verify方法,它将可以正常工作。

_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());
_myClassMock.Verify(ic => ic.DoStuffB(It.IsAny<int>()), Times.Once());

我从this问题的答案中了解到Moq会处理它。在为Setup / Verify指定表达式时,表达式中的内容是否有所不同,是否有解决方法?

2 个答案:

答案 0 :(得分:4)

这不起作用的原因:

void VerifyMany(int input)
{
    _myClassMock.Verify(ic => ic.DoStuffA(input), Times.Once());
    _myClassMock.Verify(ic => ic.DoStuffB(input), Times.Once());
}

是因为It.IsAny<int>()(在简单调用时)返回0。因此,本质上,当使用VerifyMany调用It.IsAny<int>()时,会将0传递给VerifyMany。这反过来意味着DoStuffA(0)DoStuffB(0)已通过验证(不是您可能想要的任何整数值)。

另一个调用:

_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());
_myClassMock.Verify(ic => ic.DoStuffB(It.IsAny<int>()), Times.Once());

之所以起作用,是因为从未直接调用ic => ic.DoStuffA(It.IsAny<int>()部分。它变成了一个表达式树,并且Moq仅走(或访问)该表达式树。这意味着它将在表达式树中找到It.IsAny<int>(),然后能够使用任何整数值验证对DoStuffA的调用(也在同一表达式树中找到)。 (有关表达式树的更多信息,请随时read this

您可以通过创建一个方法来完成此工作,该方法可以抽象出对Verify的调用并接受如下表达式:

void VerifyOnce(Expression<Action<ClassMockIsBasedOn>> callToVerify)
{
    _myClassMock.Verify(callToVerify, Times.Once());
}

您可以这样叫它:

VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>())

您还可以扩展VerifyOnce示例以接受多个表达式。这样一来,您就可以在一行上验证DoStuffADoStuffB

void VerifyOnce(params Expression<Action<ClassMockIsBasedOn>>[] callsToVerify)
{
    foreach(var callToVerify in callsToVerify) 
    {
        _myClassMock.Verify(callToVerify, Times.Once());
    }
}

这将允许这样的通话:

VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>(),
           ic => ic.DoStuffB(It.IsAny<int>());

当然,您可以将ClassMockIsBasedOn替换为泛型。并添加一个重载,该重载允许方法返回值(而不是作废)或接受布雷特在评论中建议的多个参数。

答案 1 :(得分:3)

$('body').on('focus',".datepicker", function(){ $(this).datepicker({ //Change this line here 仅允许Moq匹配将来的方法调用(如果在 $('body').on('focus',".datepicker", function(){ $(this).removeClass('hasDatepicker').datepicker({ //Change this line here 构造中使用,则无法使用It.IsAnySetup进行,如果您的{ {1}}尚未设置Verify。因为Assert总是返回输入的默认值。

因此,如果您想在Setup处使用It.IsAny,则应先将It.IsAny用作目标方法:

正确

It.IsAny

错误

Verify