【问题标题】:How to mock a method returning Task<IEnumerable<T>> with Task<List<T>>?如何使用 Task<List<T>> 模拟返回 Task<IEnumerable<T>> 的方法?
【发布时间】:2016-09-23 04:15:54
【问题描述】:

我正在尝试设置一个单元测试初始化​​程序(在 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
}

我遇到的问题是我不知道如何获得返回我的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&lt;myObj&gt; 并将其返回为 IEnumerable&lt;myObj&gt;,但我觉得必须有另一种更简洁的方法来处理这个问题。

那么,我如何在不创建辅助方法的情况下做到这一点?

【问题讨论】:

  • 如果不使用var 而使用IEnumerable&lt;myCustomObject&gt; objectsList = new List&lt;myCustomObject&gt;() 会怎样?
  • 仅仅因为A和B这两种类型表现出特定的继承/实现关系,那不是否意味着G&lt;A&gt;和G&lt;B&gt;表现出相同的关系。

标签: c# unit-testing moq


【解决方案1】:

您需要在Task.FromResult 上指定&lt;IEnumerable&lt;myCustomObject&gt;&gt;,如下所示:

[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&lt;myCustomObject&gt; 分配之前将您的objectList 声明为&lt;IEnumerable&lt;myCustomObject&gt;&gt;。不需要之前的建议。

【讨论】:

  • 这是有道理的。我想我曾尝试使用Returns&lt;T&gt;,但我没有考虑过FromResult&lt;T&gt;。后一个建议类似于我的解决方法,虽然它有效,但我一直在寻找如何在线进行。我只是无法完全理解它。谢谢你!
【解决方案2】:

你可以一般地转换你的原始对象:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    相关资源
    最近更新 更多