Ну, я знаю, это немного сложный случай. У меня есть серверная часть ASP.NET Core (site
), которая взаимодействует с другой системой (facade
) через http.
Но не с HttpClient
, а с клиентами, которым facade
предоставляет HttpClient
внизу.
Конструкторы этих клиентов выглядят так
public class OrdersClient : IOrdersClient
{
private HttpClient _client;
public OrdersClient(IEndpoint endpoint, HttpClient client)
{ ... }
}
И регистрация выглядит так
services
.AddHttpClient("facade-client")
.AddHttpMessageHandler<CorrelationIdDelegatingHandler>()
.AddHttpMessageHandler<HttpErrorDelegatingHandler>()
.AddTypedClient<IOrdersClient>((endpoint, client) => new OrdersClient(endpoint, client));
И конфигурация содержит (это важно!)
app.UseCorrelationId(new CorrelationIdOptions());
N.B. Для чего не нужен endpoint
в этом случае.
Ok. Поэтому я хочу проверить свой site
с новым классным WebApplicationFactory
. Я создаю его и получаю клиента на site
, как описано в документации. Для некоторых тестов я просто высмеиваю клиентов на facade
как
public TestOrdersClient: IOrdersClient
{
}
и проверь мою логику без facade
.
Приступая к делу. Я хочу протестировать обработчики, которые украшают мои HttpClient
до facade
.
Как я хочу тестировать обработчики: я регистрирую поддельный PrimaryHttpMessageHandler, чтобы он имитировал ответы от facade
в моем WebApplicationFactory
. И я добавил ImitationClient
, который использовал зарегистрированный HttpClient
.
services
.AddHttpClient("facade-client")
.ConfigurePrimaryHttpMessageHandler(() => new HttpMessageHandlerFake())
.AddTypedClient<ImitationClient>();
И вот я в беде.
В моем тесте получить ImitationClient
с завода и попытаться вызвать какой-то метод, который вызывает HttpClient
внутри.
var factory = new SiteWebApplicationFactory();
var client = factory.CreateDefaultClient();
var imitationClient =factory.Server.Host.Services.GetService<ImitationClient>();
await imitationClient.GetData();
И вот я получаю System.NullReferenceException
из-за этого обработчика:
public class CorrelationIdDelegatingHandler : DelegatingHandler
{
private readonly ICorrelationContextAccessor _correlationAccessor;
public CorrelationIdDelegatingHandler(ICorrelationContextAccessor correlationAccessor)
{
_correlationAccessor = correlationAccessor;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Add(
_correlationAccessor.CorrelationContext.Header,
_correlationAccessor.CorrelationContext.CorrelationId);
return base.SendAsync(request, cancellationToken);
}
}
Идентификатор корреляции, назначенный входящему запросу на site
, а затем перенаправленный на запросы от site
до facade
. Но когда я тестирую только клиента на facade
, у меня нет входящего запроса, нет CorrelationContext и происходит сбой.
Наконец, мой вопрос заключается в том, как правильно написать тест для внутреннего httpClient
с WebApplicationFactory
. Я знаю, что мое описание довольно запутанное, я прошу прощения за это. Я готов ответить на любые вопросы по коду и архитектуре нашего проекта. Спасибо!