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, Expression
1 expression, Condition condition)at Moq.Mock
1.Setup(Expression
1 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