簡體   English   中英

C# Azure Function 應用程序 - Moq 測試 - 添加依賴項注入失敗,CS0311

[英]C# Azure Function app - Moq Tests - Adding dependency injection fails with CS0311

我有以下 function:

public class WidgetRequest {

   [FunctionName("CreateWidget")]
    public static async Task<IActionResult> CreateWidget(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "/widget")] HttpRequest req,
         [Queue("widgets"), StorageAccount("StorageForWidgets")] ICollector<string> messageQueue,
        ILogger log)
    {           
        ProvisionedWidgetsRepository storage = new ProvisionedWidgetsRepository();
        WidgetResponse response = new WidgetResponse ();
        var content = await new StreamReader(req.Body).ReadToEndAsync();
        log.LogInformation($"Received following payload: {content}");

        var widgetRequest = JsonConvert.DeserializeObject<Widget>(content);
        if (widgetRequest .name != null){     
                //add the request to queue for processing
                messageQueue.Add(JsonConvert.SerializeObject(widgetRequest));   
                //also add to provisioned storage table             
                response = await storage.ProvisioningRequest(widgetRequest , req.HttpContext.Items["MS_AzureFunctionsRequestID"].ToString(), "enqueued");
            
        } 
        else {
            response.status = "Error: Invalid Request";
            response.requestId=null;
        }
        return new OkObjectResult(JsonConvert.SerializeObject(response));  
    }

我有以下測試:

    [Fact]
    public async void widget_creation_requests_should_be_stored_in_queue(){
        var messageQueue = TestFactory.CreateAzureStorageQueue();
        var storageTable = TestFactory.CreateAzureStorageTable();
        var request = TestFactory.CreateWidgetRequest();
        var response = (OkObjectResult)await WidgetRequest.CreateWidget(request, messageQueue, logger);
        Assert.NotNull(response);
        Assert.True(((AzureStorageQueueTestClient<string>)messageQueue).Messages.Count > 0);
    }

測試失敗是因為我不知道如何傳入我在測試中旋轉的模擬存儲表(“var storageTable”)。 在實際的function中可以看到,我手動實例化了一個新的存儲object這樣:

 ProvisionedWidgetsRepository storage = new ProvisionedWidgetsRepository();

我不傳遞它。任何提示將不勝感激。
謝謝

編輯 1

所以我重構了將存儲邏輯移出到一個單獨的 class 中,並帶有一個支持依賴注入的接口。 具有主要邏輯的代碼現在有一個構造函數,並使用新接口。 它看起來像這樣:

public class WidgetRequest {
    //Using Interface for storage so we can dependency inject for testing. 
    private IWidgetRepositoryController storage;        
    public WidgetRequest(IWidgetRepositoryController storage)
    {
        this.storage = storage;    
    }

   [FunctionName("CreateWidget")]
    public static async Task<IActionResult> CreateWidget(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "/widget")] HttpRequest req,
         [Queue("widgets"), StorageAccount("StorageForWidgets")] ICollector<string> messageQueue,
        ILogger log)
    {           
        //ProvisionedWidgetsRepository storage = new ProvisionedWidgetsRepository();
        WidgetResponse response = new WidgetResponse ();
        var content = await new StreamReader(req.Body).ReadToEndAsync();
        log.LogInformation($"Received following payload: {content}");

        var widgetRequest = JsonConvert.DeserializeObject<Widget>(content);
        if (widgetRequest .name != null){     
                //add the request to queue for processing
                messageQueue.Add(JsonConvert.SerializeObject(widgetRequest));   
                //also add to provisioned storage table             
                response = await storage.AddToTable(widgetRequest , req.HttpContext.Items["MS_AzureFunctionsRequestID"].ToString(), "enqueued");
            
        } 
        else {
            response.status = "Error: Invalid Request";
            response.requestId=null;
        }
        return new OkObjectResult(JsonConvert.SerializeObject(response));  
    }

這是新存儲 Controller class 的樣子,以及界面:

public interface IWidgetRepositoryController
{
    Task<WidgetResponse> AddToTable(Widget widgetRequest,  string requestID, string partitionName);
}
public class WidgetRepositoryController
{        
    public async Task<WidgetResponse> AddToTable(Widget widgetRequest,  string requestID, string partitionName)
    {
        ProvisionedWidgetRepository storage = new ProvisionedWidgetRepository ();
        WidgetResponse response = await storage.ProvisioningRequest(widgetRequest, requestID, partitionName);
        return response;
    }

}

到目前為止,上面的所有邏輯似乎都沒有問題——沒有錯誤。 但我現在正在嘗試創建 Startup.cs 文件。 我收到錯誤 CS0311。

這是代碼:

 [assembly: FunctionsStartup(typeof(Az.Fn.Widgets.Startup))]
 namespace Az.Fn.Widget
 {

public class Startup: FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddTransient<IWidgetRepositoryController, WidgetRepositoryController>();
    }
}

完整錯誤:

類型“Az.Fn.Widgets.WidgetRepositoryController”不能用作泛型類型或方法“ServiceCollectionServiceExtensions.AddTransient<TService, TImplementation>(IServiceCollection)”中的類型參數“TImplementation”。 沒有從“Az.Fn.Widgets.WidgetRepositoryController”到“Az.Fn.Widgets.IWidgetRepositoryController”的隱式引用轉換。

根據 ThrowingSpoon 的評論,我不得不重構以支持 DI,然后我遇到了一個錯誤。 我不得不從這個改變 WidgetRespositoryController class :

public class WorkspaceRepositoryController 

對此:

public class WorkspaceRepositoryController : IWorkspaceRepositoryController

而且好像很開心。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM