如何使用 Moq 从 IHttpClientFactory 模拟 HTTPClient 并结合 .NET Core 中的 Polly 策略

How to Mock HTTPClient from IHttpClientFactory combined with Polly policies in .NET Core using Moq

我使用 IHttpClientFactory 创建一个 HTTP 客户端并附加一个 Polly 策略(需要 Microsoft.Extensions.Http.Polly),如下所示:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;

IHost host = new HostBuilder()
    .ConfigureServices((hostingContext, services) =>
    {
        services.AddHttpClient("TestClient", client =>
        {
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        })
        .AddPolicyHandler(PollyPolicies.HttpResponsePolicies(
            arg1, 
            arg2,
            arg3));
    })
    .Build();

IHttpClientFactory httpClientFactory = host.Services.GetRequiredService<IHttpClientFactory>();

HttpClient httpClient = httpClientFactory.CreateClient("TestClient");

如何使用 Moq 模拟此 HTTP 客户端?

编辑:模拟意味着能够模拟 HTTP 的请求。应按定义应用政策。

正如 Whosebug 上许多其他帖子中所述,您不会模拟 HTTP 客户端本身,而是模拟 HttpMessageHandler:

Mock<HttpMessageHandler> handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
handlerMock
    .Protected()
    .Setup<Task<HttpResponseMessage>>(
        "SendAsync",
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>()
    )
    .ReturnsAsync(new HttpResponseMessage()
    {
        StatusCode = HttpStatusCode.OK,
        Content = new StringContent(response)
    });

为了最终拥有一个带有模拟 HttpMessageHandler 的 HTTP 客户端以及 Polly 策略,您可以执行以下操作:

IServiceCollection services = new ServiceCollection();
services.AddHttpClient("TestClient")
    .AddPolicyHandler(PollyPolicies.HttpResponsePolicies(arg1, arg2, arg3))
    .ConfigurePrimaryHttpMessageHandler(() => handlerMock.Object);

HttpClient httpClient =
    services
        .BuildServiceProvider()
        .GetRequiredService<IHttpClientFactory>()
        .CreateClient("TestClient");