使用NSubstitute模拟任务<IEnumerable <T >>

nik*_*ias 6 asp.net-mvc unit-testing nsubstitute

我有问题试图从一个接口NSubstitute返回一个IEnumerable接口Task.

工厂我在嘲笑:

public interface IWebApiFactory<T> : IDisposable
{
    <T> GetOne(int id);
    Task<IEnumerable<T>> GetAll();
    Task<IEnumerable<T>> GetMany();
    void SetAuth(string token);
}
Run Code Online (Sandbox Code Playgroud)

测试方法:

[TestMethod]
public async Task TestMutlipleUsersAsViewResult()
{
    var employees = new List<EmployeeDTO>()
    {
        new EmployeeDTO(),
        new EmployeeDTO()
    };

    // Arrange
    var factory = Substitute.For<IWebApiFactory<EmployeeDTO>>();
    factory.GetMany().Returns(Task.FromResult(employees));
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

无法从'System.Threading.Tasks.Task>转换为System.Func >>

这是一个问题,我通过一个列表,IEnumerable尽管List是这样做IEnumerable

编辑:

这些是其中的功能 NSubstitute

public static ConfiguredCall Returns<T>(this T value, Func<CallInfo, T> returnThis, params Func<CallInfo, T>[] returnThese);
public static ConfiguredCall Returns<T>(this T value, T returnThis, params T[] returnThese);
Run Code Online (Sandbox Code Playgroud)

Pan*_*vos 5

重载都不适合您传递的值。第二个签名public static ConfiguredCall Returns<T>(this T value, T returnThis, params T[] returnThese);期望与函数的返回类型具有相同类型的值,因此它不是最佳匹配。

解决此问题的最简单方法是将雇员的声明更改为IEnumerable<EmployeeDTO>

IEnumerable<EmployeeDTO> employees = new List<EmployeeDTO>()
{
    new EmployeeDTO(),
    new EmployeeDTO()
};
Run Code Online (Sandbox Code Playgroud)

  • 您预期的行为称为[协方差](https://msdn.microsoft.com/zh-cn/library/dd799517%28v=vs.110%29.aspx),并且在接口类型或委托参数上受支持。这就是为什么它可以与IEnumerable &lt;T&gt;一起使用但不能与扩展方法一起使用的原因 (2认同)
  • 明确地说,问题不是扩展方法,而是Task &lt;T&gt;在T中不协变的事实。因此,当需要Task &lt;IEnumerable &lt;X &gt;&gt;时,Task &lt;List &lt;X &gt;&gt;不是有效的参数类型。 。 (2认同)