带有Func <foo,task <list <bar =“” >>>>

时间:2018-08-15 22:09:28

标签: c# unit-testing moq

场景:

我们处在一个可怕的数据源中,需要一个神秘的语法。我们已经构建了“存储库”层,以将简单参数(原始值)转换为目标的正确语法。

我们要对该单元进行测试:

  1. 已应用正确的过滤器(可以通过检查repo的辅助方法创建的字符串来完成)
  2. (模拟的)远程数据源仅被调用一次
  3. 在调用回购协议时,我们将定义为远程数据源的(模拟)数据作为返回值传回了返回值。

例如

var expectedReturn = new List<Product> { new Product { StockNumber = "123" } };

provider.Setup(x => x.Run(It.IsAny<Func<IRemoteClient, Task<List<Product>>>>(),
    It.IsAny<string>())).ReturnsAsync(expectedReturn);

Moq在Setup行中失败,并带有NotSupportedException。我可能已经阅读了十几篇或更多的SO帖子,并且找不到为什么它不起作用。

在正常使用中,存储库将使用类似以下内容的

provider.Run(x => x.GetAsync<List<Product>>(requestBuilder.Request), "foo")

provider界面中运行的定义:

Task<T> Run<T>(Func<IRemoteClient, Task<T>> action, string name);

由于还注入了requestBuilder,因此我们可以很容易地评估出,就参数的数量和类型而言,请求是否正确构建,但是由于Mock调用失败,我们根本无法运行测试设置,所以我们永远都无法实现。

1 个答案:

答案 0 :(得分:2)

我正在使用Moq 4.9.0,并且已经在.NET Core 2.1以及使用.NET Framework的LINQPad内部进行了测试。它可以为我编译并运行,没有任何问题。我可以运行模拟设置,也可以在模拟对象上调用模拟方法,并检索预期的返回结果。

以下是我的测试代码:

class Program
{
    static void Main(string[] args)
    {
        var expectedReturn = new List<Product> { new Product { StockNumber = "123" } };

        var provider = new Mock<IProvider>();
        provider
            .Setup(x => x.Run(
                It.IsAny<Func<IRemoteClient, Task<List<Product>>>>(),
                It.IsAny<string>()))
            .ReturnsAsync(expectedReturn);

        var result = provider.Object.Run(client => client.GetAsync<List<Product>>(null), "foo");

        Console.WriteLine(result.Result[0].StockNumber);
    }
}

public interface IProvider
{
    Task<T> Run<T>(Func<IRemoteClient, Task<T>> action, string name);
}
public interface IRemoteClient
{
    Task<T> GetAsync<T>(object request);
}
public class Product
{
    public string StockNumber { get; set; }
}