【问题标题】:Moq: Callback after method invocation on a method that does not return a valueMoq:对不返回值的方法调用方法后的回调
【发布时间】:2015-02-25 18:08:59
【问题描述】:

我目前正在使用 Moq 库进行单元测试。 Moq 使我能够在模拟对象上注册回调 beforeafter 方法调用,如下所示:

Mock<IMyClass> mock = new Mock<IMyClass>();
mock.Setup(o => o.MyMethod())
  .Callback(() => Console.WriteLine("BEFORE!"))
  .Returns(true)
  .Callback(() => Console.WriteLine("AFTER!"));

但是,如果 MyMethod 没有返回值(即它具有 void 返回类型),那么我只能像这样设置一个回调:

mock.Setup(o => o.MyMethod())
  .Callback(() => Console.WriteLine("BEFORE!"));

如代码中所述,此回调发生在调用方法之前。似乎没有任何其他选项可以为 方法被调用之后指定第二个回调。

这可能吗?文档中似乎没有任何关于它的内容。我错过了什么吗?

【问题讨论】:

  • 我不确定您所说的 HandleMessage 未完成是什么意思。 HandleMessage 正在做的唯一 事情是调用waitHandle.ResetWaitOne 等待设置句柄,如果您从处于信号状态的ManualResetEvent 开始,则测试线程可能会在调用HandleMessage 之前通过WaitOne。我认为您会希望以无信号状态的ManualResetEvent 开始,然后您的处理程序将调用Set。但是,如果您尝试测试调用 HandleMessage 后发生的某些行为,则需要另一种方法。
  • 哈...我误用了 ManualResetEvent。德普。现在一切正常。我将删除我的具体案例的详细信息,因为它们会使其他发现此问题的人感到困惑。谢谢!

标签: c# unit-testing moq


【解决方案1】:

这是不可能的。

Callback的返回值为IReturnsThrows,是IReturns接口与Returns方法的组合,IThrows接口与Throws方法的组合。您可以在Returns 后面加上Callback,因为Returns 的返回值是IReturnResult,它实现了ICallback

您到底想完成什么?您的示例中的回调在调用方法之前和之后并没有真正发生,它们只是在调用方法时按步骤按顺序执行。您的 before 回调在计算返回值之前执行,然后您的 after 回调在此之后完成。连续执行两个回调没有意义,因为您可以将它们组合成一个回调。

【讨论】:

  • “您的示例中的回调实际上不会在调用方法之前和之后发生”Are you sure?(提示:看看最后一个示例。)
  • 是的,回调发生在评估 Returns 语句之前和之后(参见示例回调中的 Console.WriteLine 调用中的文本)。它们是调用方法时执行的步骤。当使用模拟对象的代码调用someObj.MyMethod()时,该方法被实际调用之前/之后没有,方法调用。
  • @Erik,我并不反对如何预期的行为会发生。是的,我相信你是对的,回调顺序是由Returns 语句的评估定义的。尽管如此,出于所有实际目的,what 所发生的正是 OP(以及 Moq 的相关文档)所描述的:第一个回调发生在 模拟方法调用之前,而第二个之后。
  • @rsenna,不,我不同意。 Returns 方法本身不是方法体,当你把CallbackReturnsThrows 等放在模拟方法调用的实现。从调用方法的代码的角度来看,所有这些事情都是作为方法调用的一部分发生的。在方法调用之前或之后发生的事情不是该方法调用的一部分,而是在调用之外完成的。
猜你喜欢
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
相关资源
最近更新 更多