如何模拟返回 Task<IEnumerable<T>> 和 Task<List<T>> 的方法?

How to mock a method returning Task<IEnumerable<T>> with Task<List<T>>?

我正在尝试设置一个单元测试初始化​​器(在 Moq 中),其中一个接口方法被模拟:

public interface IRepository
{
    Task<IEnumerable<myCustomObject>> GetSomethingAsync(string someStringParam);
}

...

[TestInitialize]
public void Initialize()
{
    var repoMock = new Mock<IRepository>();

    var objectsList = new List<myCustomObject>() {
        new myCustomObject("Something"), 
        new myCustomObject("Otherthing")
    }

    repoMock.Setup<Task<IEnumerable<myCustomObject>>>(
        rep => rep.GetSomethingAsync("ThisParam")
    ).Returns(Task.FromResult(objectsList)); //error here
}

我遇到的问题是我不知道如何获取 return 我的 objectsList 的方法。在实践中,这当然可以正常工作,因为 List 实现了 IEnumerable,但在 Moq 中包装在任务中时似乎不起作用。我得到的错误是在 Returns() 方法上:

Argument 1: cannot convert from 'System.Threading.Tasks.Task<
  System.Collections.Generic.List<myCustomObject>>'
to 'System.Threading.Tasks.Task<
  System.Collections.Generic.IEnumerable<myCustomObject>>'

作为解决方法,我 可以 创建另一种方法,它只创建 List<myObj> 和 return 将其创建为 IEnumerable<myObj>,但我觉得就像必须有另一种更清洁的方法来处理这个问题。

那么,如果不创建辅助方法,我该怎么做呢?

您需要在 Task.FromResult 上指定 <IEnumerable<myCustomObject>>,如下所示:

[TestInitialize]
public void Initialize()
{
    var repoMock = new Mock<IRepository>();

    var objectsList = new List<myCustomObject>() {
        new myCustomObject("Something"), 
        new myCustomObject("Otherthing")
    }

    repoMock.Setup<Task<IEnumerable<myCustomObject>>>(
        rep => rep.GetSomethingAsync("ThisParam")
    ).Returns(Task.FromResult<IEnumerable<myCustomObject>>(objectsList));
}

或者,您可以在从 List<myCustomObject> 分配之前将 objectList 声明为 <IEnumerable<myCustomObject>>。不需要做出之前的建议。

您可以一般地投射您的原始对象:

IEnumerable<myCustomObject> objectsList = new List<myCustomObject>() {
    new myCustomObject("Something"), 
    new myCustomObject("Otherthing")
};