【问题标题】:Delay in Moq return for async method not delaying异步方法的 Moq 返回延迟不延迟
【发布时间】:2018-06-13 00:44:57
【问题描述】:

在我的单元测试中,我试图从我的接口IPipeline 中模拟出Run() async 方法并模拟延迟,在PipelineScheduler 类中调用它

public interface IPipeline
{
    Task Run();
}

测试起订量:

[SetUp]
public void SetUp()
{
    _mockPipeline = new Mock<IPipeline>();

    _mockPipeline.Setup(x => x.Run()).Returns(async () =>
    {
        await Task.Delay(3000);
    });
    _scheduler = new PipelineScheduler(_mockPipeline.Object);
}

但是,当我在调用模拟方法的地方运行测试和调试时

await _pipeline.Run().ConfigureAwait(false);

没有延迟,在这一行之后立即继续执行。

但如果我用存根类替换模拟,延迟工作正常。

private class MockPipeline : IPipeline
{
    public async Task Run()
    {
        await Task.Delay(3000);
    }
}

[SetUp]
public void SetUp()
{
    _mockPipeline = new MockPipeline();
    _scheduler = new PipelineScheduler(_mockPipeline);
}

所以我想问题是我用最小起订量和我的存根类创建延迟的方式有什么不同?

【问题讨论】:

  • .Returns(Task.Delay(3000)); 是设置运行所需的全部内容。之前的设置很火,忘记async void
  • 那就是答案,仍然看不到问题中缺少什么。也许它可以稍微调整一下,但主体在那里。

标签: c# unit-testing asynchronous async-await moq


【解决方案1】:

不同之处在于设置配置不正确。

返回一个任务.Returns(Task.Delay(3000)); 是设置所需的全部。前面的设置很火,忘记async void,这就是前面的示例没有等待并立即继续的原因。

以下最小示例演示了应该如何设置模拟

[TestClass]
public class MyTestClass {
    [TestMethod]
    public async Task MyTestMethod() {
        //Arrange
        var _mockPipeline = new Mock<IPipeline>();

        _mockPipeline.Setup(x => x.Run()).Returns(Task.Delay(3000)).Verifiable();

        var sut = new PipelineScheduler(_mockPipeline.Object);

        //Act
        await sut.MethodUnderTest();

        //Assert
        _mockPipeline.Verify();
    }
}

public interface IPipeline {
    Task Run();
}

public class PipelineScheduler {
    private IPipeline _pipeline;

    public PipelineScheduler(IPipeline pipeline) {
        this._pipeline = pipeline;
    }

    public async Task MethodUnderTest() {

        await _pipeline.Run().ConfigureAwait(false);

    }
}

执行时,测试延迟配置的 3 秒。

【讨论】:

    【解决方案2】:

    一个老问题,但我只是遇到了问题,正确的方法是不是被接受的答案。正确的做法是在return中使用函数。

    .Returns(() => Task.Delay(3000))
    

    如果没有() =&gt;,延迟只会应用一次,即使您执行多次顺序调用,例如,如果您这样做:

    await _pipeline.Run().ConfigureAwait(false);
    await _pipeline.Run().ConfigureAwait(false);
    await _pipeline.Run().ConfigureAwait(false);
    

    在 dotnetfiddle.net 上查看 reproduction

    【讨论】:

      猜你喜欢
      • 2018-09-26
      • 2021-02-14
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      • 2013-11-29
      • 1970-01-01
      • 2019-03-13
      • 1970-01-01
      相关资源
      最近更新 更多