在最小起订量中验证时允许*任何*参数值吗?

Allow *any* parameter value when verifying in Moq?

我正在验证是否使用 Moq 调用了一个方法,但它是一个相当复杂的方法签名,我只关心一个特定参数的值。我知道 Moq 有 It.IsAny<T>(),但即使那样你仍然必须指定参数应该是什么类型。有没有办法只说 "I don't care what was passed as this parameter, in terms of type OR value"?

没有办法完成您的要求,因为 Setup 参数是一个表示强类型 C# 的表达式。例如,考虑以下方法:

void Main()
{
    Setup(() => Foo(Any()));
}

void Setup(Expression<Action> expression)
{
}

void Foo(int i)
{
}

object Any() 
{
    throw new NotImplementedException();
}

此代码无法编译,因为 Any() return 是一个 object 并且 Foo() 需要一个 int 参数。

如果我们尝试将 Any() 更改为 return dynamic:

dynamic Any() {
    throw new NotImplementedException();
}

这会产生以下错误:

CS1963 An expression tree may not contain a dynamic operation

如果不需要通用参数,根本无法使此表达式生成适用于所有可能的类型。

正如@StriplingWarrior 提到的,您必须在使用 Verify.

时指定参数

然而,Moq 确实提供了 Invocations 序列(不确定引入的是哪个版本,YMMV),因此基本上可以满足您的要求。

对于以下接口:

public interface IFoo
{
    public void Sum(int a, int b, out int sum);
}

...以下将断言 Sum 方法被调用一次 - 没有指定任何参数。

var fooMock = new Mock<IFoo>();
var foo = fooMock.Object;

foo.Sum(1, 2, out var sum);

Assert.That(fooMock.Invocations.Count(x => x.Method.Name.Equals(nameof(IFoo.Sum))), Is.EqualTo(1));

每个调用条目都有方法、参数等,因此您可以构建复杂的匹配项。