使用Moq模拟Delegate.Invoke()会在LINQ中引发InvalidCast异常

Nik*_*dze 15 c# linq delegates unit-testing moq

假设我有IService界面:

public interface IService
{
    string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

还有一个Func<IService>返回此接口的委托.

在我的单元测试中,我想Invoke()使用Moq 模拟委托的方法,如下所示:

[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
}
Run Code Online (Sandbox Code Playgroud)

不幸mockDelegate.Setup(...)抛出System.InvalidCastException:

测试方法UnitTest抛出异常:

System.InvalidCastException:无法将类型为"System.Linq.Expressions.InstanceMethodCallExpressionN"的对象强制转换为"System.Linq.Expressions.InvocationExpression".

在Moq.ExpressionExtensions.GetCallInfo(LambdaExpression表达式,模拟模拟)

在Moq.Mock.<> c_ DisplayClass1c`2.b _1b()

在Moq.PexProtector.Invoke(Func`1函数)

在Moq.Mock.Setup(模拟1 mock, Expression1表达式,条件条件)

在Moq.Mock 1.Setup(Expression1表达)

在UnitTests.cs中的UnitTest():第38行

38号线是 mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object);

我错过了什么吗?或者模拟委托调用通常不是一个好主意?

谢谢.

Luk*_*oid 37

在Moq中完成此操作是100%可行的,具体方法如下:

var mockService = new Mock<IService>();

var mockDelegate = new Mock<Func<IService>>();
mockDelegate.Setup(x => x()).Returns(mockService.Object);
Run Code Online (Sandbox Code Playgroud)

你得到的原因InvalidCastException是因为你正在创建Mock<T>一个委托类型.因此,它期望Expression是type InvocationExpression(x())而不是InstanceMethodCallExpressionN(x.Invoke()).

这也允许您验证代理的调用Mock,例如

mockDelegate.Verify(x => x(), Times.Once);
Run Code Online (Sandbox Code Playgroud)

我已将此作为答案发布,因为虽然对于这种情况可能没有必要,但知道肯定是有用的.