Протестируйте внутренний httpClient через WebApplicationFactory - PullRequest
2 голосов
/ 08 апреля 2019

Ну, я знаю, это немного сложный случай. У меня есть серверная часть 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. Я знаю, что мое описание довольно запутанное, я прошу прощения за это. Я готов ответить на любые вопросы по коду и архитектуре нашего проекта. Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...