Search code examples
c#lambdamoqxunitstub

Lambda function causing compiler error with 0 arguments, exception with 1 or more


I am using a lambda function in a C# .NET CORE environment with Moq. More specifically, I am using it in a setup method like so:

MockObject.Setup(o => o.GetList()).Returns<List<DifferentClass>>(() => Task.FromExisting(existingList));

The problem is in the .Returns() call. If I use an empty Lambda, I receive the compiler error that follows:

  error CS1593: Delegate 'Func<List<DifferentClass>,  Task<List<DifferentClass>>>' does not take 0 arguments.

This implies I need to add an argument to the lambda. I do so as follows:

MockObject.Setup(o => o.GetList()).Returns<List<DifferentClass>>(o => Task.FromExisting(existingList));

Now, rather than a compiler error, an exception is thrown:

System.ArgumentException : Invalid callback. Setup on method with 0 parameter(s) cannot invoke callback with different number of parameters (1).

The stack trace references the same line of code.

Here's the example code:

The tests:

public class UnitTest1
{
    static readonly Mock<IMyClass> MockObject;

    static UnitTest1()
    {
        MockObject = new Mock<IMyClass>();
        var existingList = new List<DifferentClass>();
        // Line causing exception below
        MockObject.Setup(o => o.GetList()).Returns<List<DifferentClass>>(() => Task.FromExisting(existingList));
    }

    // Tests go here...
    [Fact]
    Test1()
    {
        //...
    }
}

Here is the mocked class, IMyClass:

public interface IMyClass
{
    Task<List<DifferentClass>> GetList();
}

It seems like my two options are to throw an exception or fail to compile. I'm not sure what I can do here. If there's anything I'm missing please let me know.


Solution

  • Given the definition of the mocked interface, just call .ReturnsAsync(existingList); and the type will be inferred.

    static UnitTest1()
    {
        MockObject = new Mock<IMyClass>();
        var existingList = new List<DifferentClass>();
        MockObject
            .Setup(o => o.GetList())
            .ReturnsAsync(existingList);
    }