我有一个测试类,它调用MyClass
的模拟,我以前Setup
和DoStuffA
都DoStuffB
。
我尝试将多个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指定表达式时,表达式中的内容是否有所不同,是否有解决方法?
答案 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
示例以接受多个表达式。这样一来,您就可以在一行上验证DoStuffA
和DoStuffB
:
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.IsAny
或Setup
进行,如果您的{ {1}}尚未设置Verify
。因为Assert
总是返回输入的默认值。
因此,如果您想在Setup
处使用It.IsAny
,则应先将It.IsAny
用作目标方法:
正确
It.IsAny
错误
Verify