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

时间:2021-04-13 10:45:04

I'm tring to use a lambda with a multiple-params function but Moq throws this exception at runtime when I attempt to call the mock.Object.Convert(value, null, null, null); line.

我正在尝试使用带有多个参数的lambda函数,但是当我试图调用mock.Object时,Moq在运行时抛出了这个异常。转换(价值,空,空,空);线。

System.Reflection.TargetParameterCountException: Parameter count mismatch

The code is:

的代码是:

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);

What is the proper way to implement it?

什么是正确的实现方法?

4 个解决方案

#1


117  

It's your Returns clause. You have a 4 parameter method that you're setting up, but you're only using a 1 parameter lambda. I ran the following without issue:

这是你的回报条款。你设置了一个4参数的方法,但是你只使用一个参数。我毫无疑问地进行了以下操作:

[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);
}

No exceptions, test passed.

没有异常,测试通过。

#2


4  

Not an answer for OP but perhaps for future googlers:

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

I had a Callback that didn't match the signature of the method being setup

我有一个回调,它与正在安装的方法的签名不匹配

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.
    });

This was the result of some refactoring and the refactoring tool of course couldn't realise that the Callback signature was incorrect

这是一些重构的结果,当然重构工具没有意识到回调签名是错误的。

#3


1  

Perhaps it's because you are passing null but It.IsAny<Object>() is expecting any object except null? What happens if you do the following?:

可能是因为您正在传递null,但是。any ()是否期望除了null之外的任何对象?如果你做以下的事会怎么样?

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

This is just a stab in the dark from me, I'm more familiar with Rhino.Mocks.

这只是我暗地里的一刀,我更熟悉犀牛。


My 2nd guess:

我猜想2:

Having looked at the Moq.chm that comes with the download,

看了Moq。chm随下载而来,

You are using the Setup(Expression<Action<T>>) method which "Specifies a setup on the mocked type for a call to a void method."

您正在使用Setup(Expression >)方法,该方法“为对void方法的调用指定了一个受嘲弄类型的设置”。

You want te Setup<TResult>(Expression<Func<T,TResult>>) method that "Specifies a setup on the mocked type for a call to a value returning method".

您需要te Setup (表达式 >)方法,该方法“为对值返回方法的调用指定了一个模拟类型的设置”。

So you could try:

所以你可以试试:

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

#4


1  

In my case, I thought that the type in Returns<> is the output type, but in fact it was the input type(s).

在我的例子中,我认为返回<>的类型是输出类型,但实际上它是输入类型。

So if you have a method

如果你有一个方法。

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

The correct clause is .Returns<int, int>(...), NOT .Returns<string>(...) which is what I thought initially.

正确的子句是. return (…),而不是. return (…),这是我最初的想法。 ,>

My mistake was because I was testing a function with the same input and return type initially - for example public virtual string Foo(string a).

我的错误在于,我最初测试了一个具有相同输入和返回类型的函数——例如公共虚拟字符串Foo(字符串a)。

#1


117  

It's your Returns clause. You have a 4 parameter method that you're setting up, but you're only using a 1 parameter lambda. I ran the following without issue:

这是你的回报条款。你设置了一个4参数的方法,但是你只使用一个参数。我毫无疑问地进行了以下操作:

[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);
}

No exceptions, test passed.

没有异常,测试通过。

#2


4  

Not an answer for OP but perhaps for future googlers:

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

I had a Callback that didn't match the signature of the method being setup

我有一个回调,它与正在安装的方法的签名不匹配

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.
    });

This was the result of some refactoring and the refactoring tool of course couldn't realise that the Callback signature was incorrect

这是一些重构的结果,当然重构工具没有意识到回调签名是错误的。

#3


1  

Perhaps it's because you are passing null but It.IsAny<Object>() is expecting any object except null? What happens if you do the following?:

可能是因为您正在传递null,但是。any ()是否期望除了null之外的任何对象?如果你做以下的事会怎么样?

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

This is just a stab in the dark from me, I'm more familiar with Rhino.Mocks.

这只是我暗地里的一刀,我更熟悉犀牛。


My 2nd guess:

我猜想2:

Having looked at the Moq.chm that comes with the download,

看了Moq。chm随下载而来,

You are using the Setup(Expression<Action<T>>) method which "Specifies a setup on the mocked type for a call to a void method."

您正在使用Setup(Expression >)方法,该方法“为对void方法的调用指定了一个受嘲弄类型的设置”。

You want te Setup<TResult>(Expression<Func<T,TResult>>) method that "Specifies a setup on the mocked type for a call to a value returning method".

您需要te Setup (表达式 >)方法,该方法“为对值返回方法的调用指定了一个模拟类型的设置”。

So you could try:

所以你可以试试:

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

#4


1  

In my case, I thought that the type in Returns<> is the output type, but in fact it was the input type(s).

在我的例子中,我认为返回<>的类型是输出类型,但实际上它是输入类型。

So if you have a method

如果你有一个方法。

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

The correct clause is .Returns<int, int>(...), NOT .Returns<string>(...) which is what I thought initially.

正确的子句是. return (…),而不是. return (…),这是我最初的想法。 ,>

My mistake was because I was testing a function with the same input and return type initially - for example public virtual string Foo(string a).

我的错误在于,我最初测试了一个具有相同输入和返回类型的函数——例如公共虚拟字符串Foo(字符串a)。