【问题标题】:Mocking Task.Delay模拟任务.延迟
【发布时间】:2017-03-25 02:16:27
【问题描述】:

我有一个方法如下:await Task.Delay(waitTime).ConfigureAwait(false);

我有一个很好的策略来避免在单元测试时实际等待几秒钟,而是验证我们是否尝试等待特定的秒数。

例如,有没有办法在我的方法中注入一个额外的参数,就像在这个(人为的)示例中,我注入一个虚构的 ITaskWaiter 接口的模拟对象:

// Arrange
var mockWait = new Mock<ITaskWaiter>(MockBehavior.Strict);
mockWait.Setup(w => w.Delay(It.Is<TimeSpan>(t => t.TotalSeconds == 2)));

// Act
myObject.MyMethod(mockWait.Object);

// Assert
mockWait.Verify();

【问题讨论】:

    标签: c# unit-testing mocking moq


    【解决方案1】:

    你可以像这样定义一个“delayer”接口:

    public interface IAsyncDelayer
    {
        Task Delay(TimeSpan timeSpan);
    }
    

    然后您可以为生产代码提供以下实现:

    public class AsyncDelayer : IAsyncDelayer
    {
        public Task Delay(TimeSpan timeSpan)
        {
            return Task.Delay(timeSpan);
        }
    }
    

    现在,您的课程将如下所示:

    public class ClassUnderTest
    {
        private readonly IAsyncDelayer asyncDelayer;
    
        public ClassUnderTest(IAsyncDelayer asyncDelayer)
        {
            this.asyncDelayer = asyncDelayer;
        }
    
        public async Task<int> MethodUnderTest()
        {
            await asyncDelayer.Delay(TimeSpan.FromSeconds(2));
    
            return 5;
        }
    }
    

    这是Dependency Injection的基本应用。基本上,我们提取了异步等待到不同类的逻辑,并为其创建了一个接口来启用polymorphism

    在生产中,你会像这样组合你的对象:

    var myClass = new ClassUnderTest(new AsyncDelayer());
    

    现在,在您的测试中,您可以创建一个立即返回的假延迟器,如下所示:

    [TestMethod]
    public async Task TestMethod1()
    {
        var mockWait = new Mock<IAsyncDelayer>();
    
        mockWait.Setup(m => m.Delay(It.IsAny<TimeSpan>())).Returns(Task.FromResult(0));
    
        var sut = new ClassUnderTest(mockWait.Object);
    
        var result = await sut.MethodUnderTest();
    
        Assert.AreEqual(5, result);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      相关资源
      最近更新 更多