【问题标题】:How to deal with multiple callbacks with Moq unit tests?如何使用 Moq 单元测试处理多个回调?
【发布时间】:2022-09-27 21:53:56
【问题描述】:

我有一个模拟的执行器,它根据我们给参数的值在 x 次回调后断言单元。这是我的单元测试的示例代码

[Test]
[TestCase(\"foo\", false, 2)]
[TestCase(\"foo\", true, 3)]
public void CommandLineShouldBeValidTest(string parameter1, bool parameter2, int finalCallbackCounter)
{
    int initialCallbackCounter = 0;

    var executorMock = new Mock<ITaskExecutor>();
    executorMock.Setup(m => m.Execute(It.IsAny<IExecutionContext>(), It.IsAny<ITask>())).Callback<IExecutionContext, ITask>((c, it) =>
    {
        var p = (ProcessTask)it;
        initialCallbackCounter++;

        if (initialCallbackCounter == finalCallbackCounter)
        {
            Assert.AreEqual(expectedCommandLine, p.CommandLine);
        }
    });

    var macro = new Macro(parameter1, parameter2, mock.Object);
    macro.Execute();
}

目前我正在使用 finalCallbackCounter 参数,因此例如,如果我将第二个布尔参数设为 true 而不是 false,我需要将其更改为 3(我实际上在当前代码中有更多参数和案例,我只是出于问题的目的对其进行了简化)。

这种方式感觉真的很笨拙,而且不是很有未来感。这个问题有更优雅的解决方案吗?

标签: c# .net unit-testing callback moq


【解决方案1】:

您可以捕获ITasks,然后在最后断言。

Setup 不适用于断言:

var capturedTasks = new List<ITask>();

var executorMock = new Mock<ITaskExecutor>();
executorMock.Setup(m => m.Execute(
    It.IsAny<IExecutionContext>(),
    Capture.In(capturedTasks)));

var macro = new Macro(mock.Object);
macro.Execute();

if (capturedTasks.Count >= finalCallbackCounter)
{
    var p = (ProcessTask)capturedTasks[finalCallbackCounter - 1];
    Assert.AreEqual(expectedCommandLine, p.CommandLine);
}

【讨论】:

  • 这很好,谢谢,虽然我的目标是摆脱最终的回调计数器,这样我就不必将它添加为参数并为每个测试用例手动修改它
  • 所以你只想要最后的调用?即Assert.AreEqual(expectedCommandLine, capturedTasks.Cast&lt;ProcessTask&gt;().Last().CommandLine);?
  • 也不一定,有时任务会被调用 5 次以上,而我需要断言第二次调用。
猜你喜欢
  • 1970-01-01
  • 2010-12-10
  • 2014-02-14
  • 1970-01-01
  • 2011-12-24
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多