Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Azure持久HTTPStart方法中的单元测试(Rhino)DBUp_C#_Unit Testing_Rhino Mocks_Azure Durable Functions_Dbup - Fatal编程技术网

C# Azure持久HTTPStart方法中的单元测试(Rhino)DBUp

C# Azure持久HTTPStart方法中的单元测试(Rhino)DBUp,c#,unit-testing,rhino-mocks,azure-durable-functions,dbup,C#,Unit Testing,Rhino Mocks,Azure Durable Functions,Dbup,技术堆栈 数据库升级的DBUP 用于活动的Azure耐久性 Rhino模拟用于单元测试 形势 目前,我已将DB Upgrade(DBUp)语句放在HTTPStart方法中,作为持久azure函数的入口点 DeployChanges.To .SqlDatabase(connectionString) .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) .LogToConsole() .Build(); 问题 这种方法的

技术堆栈

  • 数据库升级的DBUP
  • 用于活动的Azure耐久性
  • Rhino模拟用于单元测试
  • 形势

    目前,我已将DB Upgrade(DBUp)语句放在HTTPStart方法中,作为持久azure函数的入口点

    DeployChanges.To
    .SqlDatabase(connectionString)
    .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
    .LogToConsole()
    .Build(); 
    
    问题

    这种方法的问题是DBUp使用静态类来升级DB,而我不能使用Rhino来模拟静态类上的方法

    问题

    我曾想过将DBUp部分封装在一个非静态类中,但随后需要模拟构造函数初始化。不确定这是否有效

    代码-升级DB的助手类

    public class DBUPHelper
        {
            public bool UpgradeDB()
            {
                bool status = true;
                var connectionString = "Data Source=localhost;Initial Catalog=master;Integrated Security=True;Connect Timeout=15";
                var upgrader =
                    DeployChanges.To
                        .SqlDatabase(connectionString)
                        .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly())
                        .LogToConsole()
                        .Build();
    
                var result = upgrader.PerformUpgrade();
    
                if (!result.Successful)
                {
                    status = false;
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(result.Error);
                    Console.ResetColor();
                }
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Success!");
                Console.ResetColor();
                return status;
            }
        }
    
    代码-调用Helper类的HTTPStart方法

    private static ILogger logObj;
               [FunctionName("HttpStart")]
               public static async Task<HttpResponseMessage> Run(
                   [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
                   [OrchestrationClient] DurableOrchestrationClientBase starter,
                   string functionName,
                   ILogger log, ExecutionContext context)
           {
               HttpResponseMessage response = null;            
               var config = new ConfigurationBuilder()
               .SetBasePath(context.FunctionAppDirectory)
               .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
               .AddEnvironmentVariables()
               .Build();
               Helper.Helper helper = new Helper.Helper(config.GetConnectionString("ConnString"););
               if (helper.UpgradeDB())
               {
                   log.LogInformation("DB Upgraded Successfully");
                   logObj = log;
                   try
                   {
                       var provider = new MultipartMemoryStreamProvider();
                       await req.Content.ReadAsMultipartAsync(provider);
                       Application policy = await GeneratePolicyObject(provider);
                       string instanceId = await starter.StartNewAsync(functionName, policy);
                       log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
                       response = starter.CreateCheckStatusResponse(req, instanceId);
                       response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(10));
                   }
                   catch (Exception ex)
                   {
                       response = new HttpResponseMessage();
                       log.LogCritical(ex.ToString());
                       log.LogCritical(ex.InnerException.ToString());
                       log.LogCritical(ex.StackTrace);
                       response.Content = new StringContent(ex.ToString());
                       response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                   }
               }
               else log.LogCritical("DB Upgrade Failed. Check logs for exception");
               return response;
           }
    
    私有静态ILogger logObj;
    [函数名(“HttpStart”)]
    公共静态异步任务运行(
    [HttpTrigger(AuthorizationLevel.Function,methods:“post”,Route=“orchestrators/{functionName}”)]HttpRequestMessage请求,
    [OrchestrationClient]DurableOrchestrationClientBase启动器,
    字符串函数名,
    ILogger日志,ExecutionContext(上下文)
    {
    HttpResponseMessage响应=null;
    var config=new ConfigurationBuilder()
    .SetBasePath(context.FunctionAppDirectory)
    .AddJsonFile(“local.settings.json”,可选:true,重载更改:true)
    .AddenEnvironmentVariables()
    .Build();
    Helper.Helper Helper=new Helper.Helper(config.GetConnectionString(“ConnString”););
    if(helper.UpgradeDB())
    {
    日志信息(“数据库升级成功”);
    logObj=log;
    尝试
    {
    var provider=新的MultipartMemoryStreamProvider();
    wait req.Content.ReadAsMultipartAsync(提供程序);
    应用程序策略=等待生成策略对象(提供程序);
    字符串instanceId=await starter.StartNewAsync(函数名,策略);
    LogInformation($“启动了ID为“{instanceId}”的业务流程”;
    response=starter.CreateCheckStatusResponse(请求,实例ID);
    response.Headers.RetryAfter=新的RetryConditionHeaderValue(TimeSpan.FromSeconds(10));
    }
    捕获(例外情况除外)
    {
    响应=新的HttpResponseMessage();
    LogCritical(例如ToString());
    LogCritical(例如InnerException.ToString());
    log.LogCritical(例如StackTrace);
    response.Content=newstringcontent(例如ToString());
    response.StatusCode=System.Net.HttpStatusCode.InternalServerError;
    }
    }
    else log.LogCritical(“数据库升级失败,请检查日志是否存在异常”);
    返回响应;
    }
    

    请参见突出显示的区域。我想模拟构造函数初始化,以便在单元测试时不会发生DB调用

    有人能帮忙吗


    关于Tarun

    使用抽象来避免与实现问题的紧密耦合

    public interface IDBHelper {
        bool UpgradeDB();
    }
    
    public class DBUPHelper: IDBHelper {
        //...code omitted for brevity
    }
    
    此外,由于测试中的方法是静态的,因此会暴露静态字段/属性

    public static class MyFunction {
        //At run time this will use default helper
        public static IDBHelper Helper = new DBUPHelper();
    
        private static ILogger logObj;
        [FunctionName("HttpStart")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
            [OrchestrationClient] DurableOrchestrationClientBase starter,
            string functionName,
            ILogger log, ExecutionContext context)
        {
           HttpResponseMessage response = null;      
           if (helper.UpgradeDB()) {
               log.LogInformation("DB Upgraded Successfully");
               logObj = log;
               try
               {
                   var provider = new MultipartMemoryStreamProvider();
                   await req.Content.ReadAsMultipartAsync(provider);
                   Application policy = await GeneratePolicyObject(provider);
                   string instanceId = await starter.StartNewAsync(functionName, policy);
                   log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
                   response = starter.CreateCheckStatusResponse(req, instanceId);
                   response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(10));
               }
               catch (Exception ex)
               {
                   response = new HttpResponseMessage();
                   log.LogCritical(ex.ToString());
                   log.LogCritical(ex.InnerException.ToString());
                   log.LogCritical(ex.StackTrace);
                   response.Content = new StringContent(ex.ToString());
                   response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
               }
           }
           else log.LogCritical("DB Upgrade Failed. Check logs for exception");
           return response;
        }
    }
    
    公共静态类MyFunction{
    //在运行时,这将使用默认的帮助程序
    public static IDBHelper Helper=new dbupulper();
    专用静态ILogger logObj;
    [函数名(“HttpStart”)]
    公共静态异步任务运行(
    [HttpTrigger(AuthorizationLevel.Function,methods:“post”,Route=“orchestrators/{functionName}”)]HttpRequestMessage请求,
    [OrchestrationClient]DurableOrchestrationClientBase启动器,
    字符串函数名,
    ILogger日志,ExecutionContext(上下文)
    {
    HttpResponseMessage响应=null;
    if(helper.UpgradeDB()){
    日志信息(“数据库升级成功”);
    logObj=log;
    尝试
    {
    var provider=新的MultipartMemoryStreamProvider();
    wait req.Content.ReadAsMultipartAsync(提供程序);
    应用程序策略=等待生成策略对象(提供程序);
    字符串instanceId=await starter.StartNewAsync(函数名,策略);
    LogInformation($“启动了ID为“{instanceId}”的业务流程”;
    response=starter.CreateCheckStatusResponse(请求,实例ID);
    response.Headers.RetryAfter=新的RetryConditionHeaderValue(TimeSpan.FromSeconds(10));
    }
    捕获(例外情况除外)
    {
    响应=新的HttpResponseMessage();
    LogCritical(例如ToString());
    LogCritical(例如InnerException.ToString());
    log.LogCritical(例如StackTrace);
    response.Content=newstringcontent(例如ToString());
    response.StatusCode=System.Net.HttpStatusCode.InternalServerError;
    }
    }
    else log.LogCritical(“数据库升级失败,请检查日志是否存在异常”);
    返回响应;
    }
    }
    
    可在隔离测试时替换

    public async Task TestFunction {
        //Arrange
        var helper = MockRepository.GenerateMock<IDBHelper>();        
        MyFunction.helper = helper; //<<--override default helper with mock
        helper.Stub(_ => _.UpgradeDB()).Return(false);//or true is that is what you desire
    
        //...arrange other parameters / dependencies
    
        //Act
        var actual = await MyFunction.Run(...);
    
        //Assert
        //...
    }
    
    公共异步任务TestFunction{
    //安排
    var helper=MockRepository.GenerateMock();
    
    MyFunction.helper=helper;//如果您希望能够独立地模拟和测试,那么非静态是一个不错的选择。在感谢您的响应@Nkosi中,通过模拟构造函数初始化来说明您的意思。感谢您的帮助。我添加了代码片段供参考。请注意,我对Rhino和单元测试的模拟策略并不熟悉e代码而不是图像当然,我包括了图像,这样我可以突出显示该区域。无论如何,我编辑了这个问题。解释得非常好。非常感谢。这将帮助我在单元测试中使用其他方法