Moq + 单元测试 - System.Reflection.TargetParameterCountException:参数计数不匹配

Posted

技术标签:

【中文标题】Moq + 单元测试 - System.Reflection.TargetParameterCountException:参数计数不匹配【英文标题】:Moq + Unit Testing - System.Reflection.TargetParameterCountException: Parameter count mismatch 【发布时间】:2011-12-04 14:23:38 【问题描述】:

我正在尝试使用带有多参数函数的 lambda,但当我尝试调用 mock.Object.Convert(value, null, null, null); 行时,Moq 在运行时抛出此异常。

System.Reflection.TargetParameterCountException:参数计数不匹配

代码是:

var mock = new Mock<IValueConverter>();

mock.Setup(conv => conv.Convert(It.IsAny<Object>(), It.IsAny<Type>(),
    It.IsAny<Object>(), It.IsAny<CultureInfo>())).Returns((Int32 num) => num + 5);

var value = 5;
var expected = 10;
var actual = mock.Object.Convert(value, null, null, null);

实现它的正确方法是什么?

【问题讨论】:

【参考方案1】:

这是您的 Returns 子句。您正在设置一个 4 参数方法,但您只使用 1 参数 lambda。我运行以下没有问题:

[TestMethod]
public void IValueConverter()

    var myStub = new Mock<IValueConverter>();
    myStub.Setup(conv => conv.Convert(It.IsAny<object>(), It.IsAny<Type>(), It.IsAny<object>(), It.IsAny<CultureInfo>())).
        Returns((object one, Type two, object three, CultureInfo four) => (int)one + 5);

    var value = 5;
    var expected = 10;

    var actual = myStub.Object.Convert(value, null, null, null);

    Assert.AreEqual<int>(expected, (int) actual);

无异常,测试通过。

【讨论】:

我打算询问这是否是对框架的测试,但我想我会怀疑可能是尝试让 Mock 到的临时代码举止得体。 我想也是,但它还是让我笑了。 我听到了。当我执行代码时,我想“是的,框架库仍在工作”。 :)【参考方案2】:

不是 OP 的答案,但也许是未来的谷歌人的答案:

我的Callback 与正在设置的方法的签名不匹配

Mock
    .Setup(r => r.GetNextCustomerNumber(It.IsAny<int>()))
    .Returns(AccountCounter++)
    .Callback<string, int>(badStringParam, leadingDigit =>
    
        // Doing stuff here, note that the 'GetNextCustomerNumber' signature is a single int 
        // but the callback unreasonably expects an additional string parameter.
    );

这是一些重构的结果,重构工具当然无法意识到Callback签名不正确

【讨论】:

哇,在我读到你的帖子之前,我一直在努力解决同样的问题,并且一直在掩盖回调。非常有帮助,我很高兴你发布它。 这也是我的问题。我为方法添加了一个参数,修复了 Setup() 调用,但错过了 Callback() 参数。【参考方案3】:

也许是因为您传递了nullIt.IsAny&lt;Object&gt;() 期待任何object 除了null?如果您执行以下操作会发生什么?:

var actual = mock.Object.Convert(value, new object(), typeof(object), CultureInfo.CurrentCulture);

这只是我在黑暗中的一个刺,我更熟悉Rhino.Mocks。


我的第二个猜测:

查看了下载附带的 Moq.chm,

您正在使用 Setup(Expression&lt;Action&lt;T&gt;&gt;) 方法,该方法“指定模拟类型的设置以调用 void 方法。”

您希望 Setup&lt;TResult&gt;(Expression&lt;Func&lt;T,TResult&gt;&gt;) 方法“指定模拟类型的设置以调用值返回方法”。

所以你可以试试:

mock.Setup<Int32>(
    conv => 
        conv.Convert(
            It.IsAny<Object>(), 
            It.IsAny<Type>(),
            It.IsAny<Object>(), 
            It.IsAny<CultureInfo>());
        return  num + 5;
        );

【讨论】:

mock.Setup 将返回类型推断为 Object,因为 Convert 方法返回一个 Object。【参考方案4】:

在我的例子中,我认为Returns&lt;&gt; 中的类型是输出类型,但实际上它是输入类型。

如果你有方法

public virtual string Foo(int a, int b)  ... 

正确的子句是.Returns&lt;int, int&gt;(...),而不是我最初想的.Returns&lt;string&gt;(...)

我的错误是因为我最初测试的是具有相同输入和返回类型的函数 - 例如public virtual string Foo(string a)

【讨论】:

以上是关于Moq + 单元测试 - System.Reflection.TargetParameterCountException:参数计数不匹配的主要内容,如果未能解决你的问题,请参考以下文章

C#单元测试--如何使用moq.mock进行依赖注入

使用 moq 对实体框架进行单元测试

如何使用moq生成假数据进行单元测试?

使用 Moq 模拟单元测试的异步方法

这个 Moq 单元测试应该(假)检索列表有啥问题?

c#单元测试:使用Moq框架Mock对象