【问题标题】:Mocking Delegate.Invoke() using Moq throws InvalidCast exception in LINQ使用 Moq 模拟 Delegate.Invoke() 在 LINQ 中引发 InvalidCast 异常
【发布时间】:2014-01-23 01:28:01
【问题描述】:

假设我有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 expression, Mock mock)

在 Moq.Mock.c_DisplayClass1c`2.b_1b()

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

在 Moq.Mock.Setup(Mock1 mock, Expression1 表达式, Condition 条件)

在 Moq.Mock1.Setup(Expression1 表达)

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

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

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

谢谢。

【问题讨论】:

  • 没有理由这样做。自己做一个代表就行了。
  • 谢谢!仍然很有趣,为什么会有一个例外......
  • @NikolaiSamteladze 出现异常是因为 Moq 不支持这种情况,但不是抛出 NotSupportException,而是得到这个不太好的 InvalidCastException。这是我认为的一个错误,因此应该在此处修复异常类型......但无论如何你都应该不要模拟委托,只需写:Func&lt;IService&gt; mockDelegate = () =&gt; mockService.Object;
  • 是的,正是这样做的。感谢您提供有关异常的详细信息。
  • 添加了 cmets 摘要作为答案。如果没人愿意再放一张,明天会接受。

标签: c# linq unit-testing delegates moq


【解决方案1】:

在起订量中 100% 可以做到这一点,方法如下:

var mockService = new Mock<IService>();

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

您获得InvalidCastException 的原因是因为您正在创建一个委托类型的Mock&lt;T&gt;。因此它期望Expression 的类型为InvocationExpression (x()) 而不是InstanceMethodCallExpressionN (x.Invoke())。

这还允许您验证您的 Mock 委托的调用,例如

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

我已将此作为答案发布,因为虽然在这种情况下可能没有必要,但知道它肯定会很有用。

【讨论】:

  • 谢谢!今天一定会试试的。
  • 感谢您的回答!工作过
【解决方案2】:

这个答案是SLaksnemesv cmets 的总结。

首先没有理由嘲笑Func&lt;IService&gt;delegate。相反,可以写:

[TestMethod]
public void UnitTest()
{
    var mockService = new Mock<IService>();

    Func<IService> mockDelegate = () => mockService.Object;

    // The rest of the test
}

存在例外是因为 Moq 不支持此方案。但是,与其抛出NotSupportException,不如使用InvalidCastException

【讨论】:

  • 如我的回答所示,Moq 支持此功能,InvalidCastException 是因为该功能使用不正确。
猜你喜欢
  • 1970-01-01
  • 2016-12-15
  • 2017-07-11
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多