Я создал специальную библиотеку, которая автоматически настраивает политики Polly для определенных служб, зависящих от HttpClient
.
Это делается с использованием IServiceCollection
методов расширения и типизированного клиентского подхода. Упрощенный пример:
public static IHttpClientBuilder SetUpFooServiceHttpClient(this IServiceCollection services)
{
return services
.AddHttpClient<FooService>()
.AddPolicyHandler(GetRetryPolicy());
}
public class FooService
{
private readonly HttpClient _client;
public FooService(HttpClient httpClient)
{
_client = httpClient;
}
public void DoJob()
{
var test = _client.GetAsync("http://example.com");
}
}
Обратите внимание, что в моем реальном коде используется универсальный тип и конструктор параметров, но я опустил эту часть, чтобы не усложнять. Цель моих тестов - подтвердить, что мой конструктор параметров правильно применяет политики, которые я хочу применить. В качестве примера давайте просто предположим, что это жестко запрограммированная политика повторных попыток, которую я хочу протестировать.
Теперь я хочу проверить, правильно ли эта библиотека регистрирует политики Polly для моих внедренных HttpClient
зависимостей.
Примечание
В Интернете и на StackOverflow можно найти множество ответов, в которых предлагается создатьHttpClient
самостоятельно, то есть:new HttpClient(new MyMockedHandler());
, но это побеждает Моя цель - проверить, действительно лиIHttpClientFactory
создает http-клиентов с запрошенными политиками.
С этой целью я хочу протестировать с настоящим HttpClient
, который был сгенерирован настоящим IHttpClientFactory
, но я хочу, чтобы его обработчик был имитирован, чтобы я мог избежать реальных веб-запросов. и искусственно вызывать плохие отзывы.
Я использую AddHttpMessageHandler()
, чтобы внедрить имитацию обработчика, но фабрика, похоже, это игнорирует.
Вот мой тестовый образец:
public class BrokenDelegatingHandler : DelegatingHandler
{
public int SendAsyncCount = 0;
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
SendAsyncCount++;
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError));
}
}
private BrokenDelegatingHandler _brokenHandler = new BrokenDelegatingHandler();
private FooService GetService()
{
var services = new ServiceCollection();
services.AddTransient<BrokenDelegatingHandler>();
var httpClientBuilder = services.SetUpFooServiceHttpClient();
httpClientBuilder.AddHttpMessageHandler(() => _brokenHandler);
services.AddSingleton<FooService>();
return services
.BuildServiceProvider()
.GetRequiredService<FooService>();
}
А вот и мой тест:
[Fact]
public void Retries_client_connection()
{
int retryCount = 3;
var service = GetService();
_brokenHandler.SendAsyncCount.Should().Be(0); // PASS
var result = service.DoJob();
_brokenHandler.SendAsyncCount.Should().Be(retryCount); // FAIL: expected 3 but got 0
}
Когда я отлаживаю тест, точка останова обработчика никогда не срабатывает, и ответ возвращается как 200 (потому что он фактически подключен к URL-адресу, а не попадает в поддельный обработчик).
Почему фабрика HTTP-клиентов игнорирует мой имитируемый обработчик?
Обратите внимание, что я также приму любой ответ, который позволит мне протестировать политики другим допустимым способом.
Я знаю, что могу просто использовать неработающую строку URL-адреса, но мне нужно будет протестировать определенные HTTP-ответы в моих тестах.