首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用It.IsAny作为参数?

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

Stack Overflow用户
提问于 2019-02-14 08:14:46
回答 2查看 1.5K关注 0票数 6

我有一个调用MyClass模拟的测试类,之前我已经同时调用了DoStuffADoStuffB

我尝试在一个方法中封装几个Verify调用,如下所示:

代码语言:javascript
运行
复制
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调用验证方法,它就会工作:

代码语言:javascript
运行
复制
_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());
_myClassMock.Verify(ic => ic.DoStuffB(It.IsAny<int>()), Times.Once());

我从问题的答案中了解到,当指定用于设置/验证时,Moq在表达式中对It.IsAny的处理方式不同,有什么解决办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-14 08:38:20

这不起作用的原因是:

代码语言:javascript
运行
复制
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)将被验证(而不是您可能想要的任何整数值)。

另一种调用:

代码语言:javascript
运行
复制
_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的调用(它也在同一表达式树中找到该调用)。(有关表达式树的更多信息,请访问阅读这篇文章)

您可以通过创建一个将对Verify的调用抽象出来并接受如下表达式的方法来使其半工作:

代码语言:javascript
运行
复制
void VerifyOnce(Expression<Action<ClassMockIsBasedOn>> callToVerify)
{
    _myClassMock.Verify(callToVerify, Times.Once());
}

这样你就可以这样称呼:

代码语言:javascript
运行
复制
VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>())

还可以扩展VerifyOnce示例以接受多个表达式。这将允许您在一行中验证DoStuffADoStuffB

代码语言:javascript
运行
复制
void VerifyOnce(params Expression<Action<ClassMockIsBasedOn>>[] callsToVerify)
{
    foreach(var callToVerify in callsToVerify) 
    {
        _myClassMock.Verify(callToVerify, Times.Once());
    }
}

这样就可以打电话了:

代码语言:javascript
运行
复制
VerifyOnce(ic => ic.DoStuffA(It.IsAny<int>(),
           ic => ic.DoStuffB(It.IsAny<int>());

当然,您可以用泛型替换ClassMockIsBasedOn。并添加重载,该重载允许返回值(而不是无效)或接受多个参数的方法,如Brett在注释中所建议的那样。

票数 5
EN

Stack Overflow用户

发布于 2019-02-14 08:21:38

It.IsAny只允许Moq匹配将来调用方法的调用(如果在Setup构造中使用),如果您的Setup尚未设置It.IsAny,则不能使用VerifyAssert进行调用。因为It.IsAny总是返回输入的默认值。

因此,如果您想在It.IsAny at Verify上使用Setup,那么首先应该为Setup方法设置目标:

校正

代码语言:javascript
运行
复制
_myClassMock.Setup(ic => ic.DoStuffA(It.IsAny<int>())).Returns(// Something here);
_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());

错误

代码语言:javascript
运行
复制
_myClassMock.Setup(ic => ic.DoStuffA(1)).Returns(// Something here);
_myClassMock.Verify(ic => ic.DoStuffA(It.IsAny<int>()), Times.Once());
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54685818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档