The mocking task.

I have a method with the following line: await Task.Delay(waitTime).ConfigureAwait(false);

I have a good strategy to avoid waiting a few seconds while testing the modules and instead verify that we tried to wait a certain number of seconds.

For example, there is a way to insert an additional parameter into my method, as in this (far-fetched) example, where I insert a mock object of a dummy interface 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();
+4
source share
1 answer

You can define a delayer interface as follows:

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

Your class will now 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;
    }
}

Injection Dependency. , , 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);
}
+6

Source: https://habr.com/ru/post/1660452/


All Articles