簡體   English   中英

重試 polly 單元測試(xunit 和 moq)

[英]retry polly unit testing (xunit and moq)

我有 .net 核心 weabpi(見下面的代碼)。 我正在使用 polly 重試策略(請參閱下面的策略)。 我想對端點(getProducts)進行單元測試並測試 polly 重試

我找到了這些示例,但不清楚如何對端點進行單元測試和重試策略?

services
  .AddHttpClient<IProductService, ProductService>()
  .AddPolicyHandler(GetRetryPolicy(3, 2)); 

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(int retryCount, int breakDuration)
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .WaitAndRetryAsync(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(breakDuration,
            retryAttempt)));
}

.Net核心api:

public interface IProductService
{
    Task<IEnumerable<ProductResponse>> GetProducts(string productType);
}
public class ProductService: IProductService
{ 
    private readonly HttpClient _httpClient;
    
    public ProductService(HttpClient httpClient)
    {
         _httpClient = httpClient;
    }
    
    public async Task<IEnumerable<ProductResponse>> GetProducts(string productType)
    {
         var response = await _httpClient.GetAsync("uri");
         ...
    }
}

第一的

我建議您在策略中添加帶有抖動退避的等待和重試

像這樣的東西:

var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromMilliseconds(100), policyRetryCount);

            RetryPolicy retryPolicy = Policy
                            .Handle<YourException>()
                            .WaitAndRetry(delay);

然后,只需Mock您的服務並對其進行測試,例如:

Mock<IProductService> mockedProductService = new Mock<IProductService>();

mockedProductService.Setup(service => service.GetProducts(productType))
                                             .ThrowsYourException();

var result = yourTestingMehtod

Assert.IsNotNull(result);
mockedProductService.Verify(service => service.GetProducts(productType), Times.Exactly(expectedServiceCall));
// example, expectedServiceCall is when you set retryCount 3, it will be 4

更新

我想您正在調用您的服務,例如:

retryPolicy.Execute(() => productService.GetProducts())

可悲的事實是,您無法真正對重試+端點邏輯進行單元測試,這是我的理由:

  1. 重試通過 DI ( AddPolicyHandler ) 在HttpClient的頂部注冊。 當您進行單元測試時,您不依賴於 DI,而是依賴於單個組件。
    1.1 因此,集成測試可能更適合於此。 我已經詳細說明了如何通過WireMock.Net做到這一點: 12 基本思想是使用預定義的響應序列創建一個本地 http 服務器(模擬下游系統)。
  2. 使用最大重試次數和時間懲罰定義重試策略后,您將無法輕松檢索它們。 因此,從單元測試的角度來看,很難確保策略已正確定義(例如延遲以seconds為單位,而不是以minutes為單位)。 我已經為此創建了一個 github 問題,但不幸的是 V8 的開發陷入了困境。

回到你的測試用例。 用 given-when-then 結構表達測試場景的正確方法應該這樣寫

  • 給定一個錯誤的下游服務,它返回 5XX 響應
  • 我打電話給 GetProducts
  • 然后執行 4 次(1 次初始 + 3 次重試嘗試)

這不是單元測試。 它更像是一個組件/集成測試。 為什么? 因為即使您可以創建一個 HttpClient 模擬,但在這種情況下,那里不會重試策略。

有一個解決方法:您可以通過PolicyHttpMessageHandler使用策略手動裝飾底層處理程序 但這在單元測試中是個壞主意,因為您基本上在測試中重新實現了 DI 部分。 這樣,您將測試您的測試安排代碼,而不是您的生產代碼。

暫無
暫無

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

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