I have a method with the following line: await Task.Delay(waitTime).ConfigureAwait(false);
I there a good strategy to avoid actually waiting the few seconds when unit testing and instead verify that we tried to wait a specific number of seconds.
For instance, is there a way to inject an additional parameter into my method like in this (contrived) example where I inject a mocked object of a fictitious ITaskWaiter
interface:
// 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();
You can define a "delayer" interface like this:
public interface IAsyncDelayer
{
Task Delay(TimeSpan timeSpan);
}
And then you can provide the following implementation for production code:
public class AsyncDelayer : IAsyncDelayer
{
public Task Delay(TimeSpan timeSpan)
{
return Task.Delay(timeSpan);
}
}
Now, your class would look something like this:
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;
}
}
This is basic application of Dependency Injection. Basically, we extracted the logic of asynchronously waiting to a different class and created an interface for it to enable polymorphism.
In production, you would compose your object like this:
var myClass = new ClassUnderTest(new AsyncDelayer());
Now, in your test you can create a fake delayer that returns immediately like this:
[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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With