C# 带Func的最小起订量<;Foo,Task<;列表<;酒吧>&燃气轮机&燃气轮机&燃气轮机;

C# 带Func的最小起订量<;Foo,Task<;列表<;酒吧>&燃气轮机&燃气轮机&燃气轮机;,c#,unit-testing,moq,C#,Unit Testing,Moq,情景: 我们正处在一个令人愉快的场景中,一个可怕的数据源需要一个神秘的语法。我们已经构建了“存储库”层,用于将简单参数(基本值)转换为目标的正确语法 我们希望进行单元测试: 已应用正确的筛选器(可以通过检查repo的helper方法创建的字符串来完成) (模拟的)远程数据源只调用一次 在调用repo时,我们将远程数据源定义为返回的(模拟的)数据作为返回值传回 比如说 var expectedReturn = new List<Product> { new Product { Stoc

情景:

我们正处在一个令人愉快的场景中,一个可怕的数据源需要一个神秘的语法。我们已经构建了“存储库”层,用于将简单参数(基本值)转换为目标的正确语法

我们希望进行单元测试:

  • 已应用正确的筛选器(可以通过检查repo的helper方法创建的字符串来完成)
  • (模拟的)远程数据源只调用一次
  • 在调用repo时,我们将远程数据源定义为返回的(模拟的)数据作为返回值传回 比如说

    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);
    
    磨合
    提供程序接口的定义:

    Task<T> Run<T>(Func<IRemoteClient, Task<T>> action, string name);
    
    任务运行(Func操作,字符串名称);
    

    由于requestBuilder也被注入,我们可以很容易地评估请求在参数的数量和类型方面是否正确构建,但我们根本无法运行测试,因为
    Mock
    调用无法完成设置,因此我们永远无法完成设置。

    我使用的是Moq 4.9.0,并且已经在.NET Core 2.1上进行了测试,以及使用.NET框架的LINQPad内部。它为我编译和运行没有任何问题。我能够运行mock安装程序,也能够对mock对象调用mocked方法,并检索预期的返回结果

    以下是我的测试代码:

    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; }
    }
    
    类程序
    {
    静态void Main(字符串[]参数)
    {
    var expectedReturn=new List{new Product{StockNumber=“123”};
    var provider=new Mock();
    供应商
    .Setup(x=>x.Run(
    It.IsAny(),
    It.IsAny())
    .ReturnsAsync(预期返回);
    var result=provider.Object.Run(client=>client.GetAsync(null),“foo”);
    Console.WriteLine(result.result[0].StockNumber);
    }
    }
    公共接口IProvider
    {
    任务运行(Func操作,字符串名称);
    }
    公共接口IRemoteClient
    {
    任务GetAsync(对象请求);
    }
    公共类产品
    {
    公共字符串StockNumber{get;set;}
    }
    
    如果您更愿意执行
    .Returns(Task.FromResult(expectedReturn))
    我的过于简化的示例似乎还有一些其他问题。你说得对,这似乎管用。我最终决定
    Run()。
    
    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; }
    }