2016-11-10 113 views
4

我有以下行的方法:await Task.Delay(waitTime).ConfigureAwait(false);嘲讽Task.Delay

我有一个很好的策略,以避免实际等待几秒钟时,单元测试和验证,而不是我们试图等待几秒钟的具体数量。

例如,有一种方法在那里我注入一个虚构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(); 

回答

6

可以定义一个“延时器”的界面是这样的:

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); 
}