如何Moq a Task.WhenAll()

时间:2017-08-15 21:17:45

标签: c# unit-testing moq

我目前有一个创建响应数组的函数。正如您在下面的代码中看到的,我正在运行 Task.WhenAll 这将抓取我的arrayOfRequests中的每个对象,并通过我的 FunctionThatCreatesResponse 运行它,返回 arrayOfRequests

中的> EACH 对象
var arrayOfRequests = new [] { RequestObject1, RequestObject2, RequestObject3 }
var arrayOfResponses = await Task.WhenAll(arrayOfRequests.Select(req => FunctionThatCreatesResponse(req)));

private async Task<ResponseObject> FunctionThatCreatesResponse(RequestObject req)
{
    // The response will be created here and returned
}

如何模拟 task.WhenAll()返回预先定义的 arrayOfResponses

有些事情:

var task = new Mock<Task>();
task.Setup(t => t.WhenAll()).ReturnsAsync(arrayOfResponses);

1 个答案:

答案 0 :(得分:0)

FunctionThatCreatesResponse或者该函数中的内容是需要公开的,以便能够模拟Task的返回。一旦提供了正确的数据,Task.WenAll将执行其设计的功能。

根据评论你还表示

  

这是一个只在该函数中被调用的内部方法。

一个选项是公开所需的功能。

//A single responsibility abstraction
public interface IClient {
    Task<ResponseObject> CreatesResponse(RequestObject req);
}

public class ExampleClass {
    private readonly IClient client;

    public ExampleClass(IClient client) {
        this.client = client;
    }

    public async Task<ResponseObject[]> GetResponses(RequestObject[] arrayOfRequests){
        var arrayOfResponses = await Task.WhenAll(arrayOfRequests
            .Select(req => client.CreatesResponse(req)));
        return arrayOfResponses;
    }
}

所以现在被测对象已被重构,可以运用被测方法并确定其行为。

public async Task ExampleClass_GetResponses_Should_Return_ResponseArray() {
    //Arrange
    var factoryMock = new Mock<IClient>();
    factoryMock.Setup(_ => _.CreatesResponse(It.IsAny<RequestObject>()))
               .Returns(() => Task.FromResult(new ResponseObject()));

    var sut = new ExampleClass(factoryMock.Object);
    var arrayOfRequests = new [] { RequestObject1, RequestObject2, RequestObject3 };

    //Act
    var actual = await sut.GetResponses(arrayOfRequests);

    //Assert
    Assert.IsNotNull(actual);
    //...assert desired behavior
}

IClient的实现将封装实际功能,并应在组合根目录中注册。