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

假设我有IService接口:

 public interface IService { string Name { get; set; } } 

以及返回此接口的委托Func

在我的unit testing中,我想使用Moq模拟委托的Invoke()方法,如下所示:

 [TestMethod] public void UnitTest() { var mockService = new Mock(); var mockDelegate = new Mock<Func>(); mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object); // The rest of the test } 

不幸的是, mockDelegate.Setup(...)抛出System.InvalidCastException

测试方法UnitTest抛出exception:

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, Expression 1表达式,条件条件)

在Moq.Mock 1.Setup(Expression 1表达式)

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

第38行是mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object);

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

谢谢。

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

 var mockService = new Mock(); var mockDelegate = new Mock>(); mockDelegate.Setup(x => x()).Returns(mockService.Object); 

您获得InvalidCastException的原因是因为您正在创建委托类型的Mock 。 因此,期望Expression的类型为InvocationExpressionx() )而不是InstanceMethodCallExpressionNx.Invoke() )。

这也允许您validationMock委托的调用,例如

 mockDelegate.Verify(x => x(), Times.Once); 

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

这个答案是对SLaksnemesv评论的总结。

没有理由首先模拟Func delegate 。 相反,人们可以写:

 [TestMethod] public void UnitTest() { var mockService = new Mock(); Func mockDelegate = () => mockService.Object; // The rest of the test } 

例外是因为Moq不支持这种情况。 但是,不是抛出NotSupportException而是InvalidCastException