繁体   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