假设我有IService
界面:
public interface IService
{
string Name { get; set; }
}
返回此接口的委托Func<IService>
。
在我的单元测试中,我想使用Moq模拟委托的Invoke()
方法,如下所示:
[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
}
不幸的是mockDelegate.Setup(...)
会引发System.InvalidCastException
:
测试方法 UnitTest引发了异常:
System.InvalidCastException:无法转换类型的对象“System.Linq.Expressions.InstanceMethodCallExpressionN”来 输入'System.Linq.Expressions.InvocationExpression'。
在Moq.ExpressionExtensions.GetCallInfo(LambdaExpression表达式,模拟模拟)
在Moq.Mock&LT;&GT; 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);
我错过了什么吗?或者模拟委托调用通常不是一个好主意?
谢谢。
答案 0 :(得分:36)
在Moq中这是100%可能的,这是如何:
var mockService = new Mock<IService>();
var mockDelegate = new Mock<Func<IService>>();
mockDelegate.Setup(x => x()).Returns(mockService.Object);
您获得InvalidCastException
的原因是因为您正在创建委托类型的Mock<T>
。因此,期望Expression
的类型为InvocationExpression
(x()
),而不是InstanceMethodCallExpressionN
(x.Invoke()
)。
这也允许您验证Mock
代表的调用,例如
mockDelegate.Verify(x => x(), Times.Once);
我已将此作为答案发布,因为虽然对于这种情况可能没有必要,但知道它肯定是有用的。
答案 1 :(得分:1)
此答案是SLaks
和nemesv
条评论的摘要。
首先没有理由嘲笑Func<IService>
delegate
。相反,人们可以写:
[TestMethod]
public void UnitTest()
{
var mockService = new Mock<IService>();
Func<IService> mockDelegate = () => mockService.Object;
// The rest of the test
}
存在异常,因为Moq不支持此方案。但是,不要抛出NotSupportException
而不是那么好InvalidCastException
。