Moq + Unit Testing - System.Reflection.TargetParameterCountException: Parameter count mismatch

C#WpfUnit TestingMoqIvalueconverter

C# Problem Overview


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.

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?

C# Solutions


Solution 1 - C#

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:

[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.

Solution 2 - C#

Not an answer for OP but perhaps for future googlers:

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

Solution 3 - C#

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?:

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:

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

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

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".

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

Solution 4 - C#

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.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmyermianView Question on Stackoverflow
Solution 1 - C#Erik DietrichView Answer on Stackoverflow
Solution 2 - C#fiatView Answer on Stackoverflow
Solution 3 - C#GrokodileView Answer on Stackoverflow
Solution 4 - C#sashoalmView Answer on Stackoverflow