Alexander Pope
Alexander Pope

Reputation: 1224

Why does Moq sometimes require explicit type declaration in Returns?

Why does this work Returns((string food) => eat(food)) while this doesn't: Returns(food => eat(food)) ?

Full working example:

class Program
{
    static void Main(string[] args)
    {
        var animal = new Mock<IAnimal>();
        Func<string, string> eat = food => $"Nom nom nom {food}";

        // works
        animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(eat);

        // works
        animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food));

        //cannot convert lambda expression to type 'string' because it is not a delegate type
        animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => eat(food));

        //cannot convert lambda expression to type 'string' because it is not a delegate type
        animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => $"Nom nom nom {food}");
    }
}

public interface IAnimal
{
    string Eat(string food);
}

Upvotes: 0

Views: 236

Answers (1)

AndrewP
AndrewP

Reputation: 1618

Replying as an answer so I can paste some code...

It's not the number of overloads as Lasse V. Karlsen suggests. The behaviour is due to casting. See comments in code below:

//works because "eat" knows it's own input type
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(eat);

// works because you are explicitly typing input param
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food));

However, things get a bit trickier when you use a lambda expression, because the lambda expression doesn't actually have an input type

animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => eat(food));
// is equivalent to:
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns((string food) => {return eat(food); });

But {return eat(food);} doesn't know what type food is.

Thus, when you call

animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => eat(food));
animal.Setup(a => a.Eat(It.IsAny<string>())).Returns(food => $"Nom nom nom {food}");

the compiler does not know what type food is.

Upvotes: 1

Related Questions