Let's say that I have IService interface:
public interface IService
{
string Name { get; set; }
}
And a delegate Func<IService> that returns this interface.
In my unit test I want to mock the delegate's Invoke() method using Moq like this:
[TestMethod]
public void UnitTest()
{
var mockService = new Mock<IService>();
var mockDelegate = new Mock<Func<IService>>();
mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object);
// The rest of the test
}
Unfortunately mockDelegate.Setup(...) throws System.InvalidCastException:
Test method UnitTest threw exception:
System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.InvocationExpression'.
at Moq.ExpressionExtensions.GetCallInfo(LambdaExpression expression, Mock mock)
at Moq.Mock.<>c_DisplayClass1c`2.b_1b()
at Moq.PexProtector.Invoke(Func`1 function)
at Moq.Mock.Setup(Mock
1 mock, Expression1 expression, Condition condition)at Moq.Mock
1.Setup(Expression1 expression)at UnitTest() in UnitTests.cs: line 38
Line 38 is mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object);
Am I missing something? Or mocking delegate invocation is generally not a good idea?
Thank you.
It is 100% possible to do this in Moq, here is how:
var mockService = new Mock<IService>();
var mockDelegate = new Mock<Func<IService>>();
mockDelegate.Setup(x => x()).Returns(mockService.Object);
The reason you were getting the InvalidCastException was because you are creating a Mock<T> of a delegate type. Thus it is expecting the Expression to be of type InvocationExpression (x()) rather than InstanceMethodCallExpressionN (x.Invoke()).
This also allows you to verify invocations of your Mock delegate, e.g.
mockDelegate.Verify(x => x(), Times.Once);
I have posted this as an answer because while it may not be necessary for this situation, it can certainly be useful to know.
This answer is a summary of SLaks and nemesv comments.
There is no reason to mock Func<IService> delegate in the first place. Instead one can write:
[TestMethod]
public void UnitTest()
{
var mockService = new Mock<IService>();
Func<IService> mockDelegate = () => mockService.Object;
// The rest of the test
}
The exception is there because because this scenario is not supported by Moq. But instead of throwing a NotSupportException you get not so nice InvalidCastException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With