http типизированный клиент в модульном тестировании сети - PullRequest
0 голосов
/ 10 июня 2019

Как я собираюсь провести модульное тестирование службы, которая делает звонки клиенту, набранному по протоколу http? примеры, приведенные на https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.2#typed-clients, не используют интерфейс.

public GitHubService(HttpClient client)

Требуется ли создание интерфейса для типизированного клиента для модульного тестирования с использованием xunit / moq? или мне не нужно было бы тестировать эту услугу.

Ответы [ 2 ]

1 голос
/ 10 июня 2019

Если ваш класс обслуживания спроектирован правильно, модульное тестирование не имеет большого смысла.Вы методы должны в значительной степени просто инкапсулировать вызовы к HttpClient, абстрагировать URL / заголовки / детали подключения / и т.д.Вы можете быть достаточно уверены, что HttpClient работает в общем смысле, так что по сути нет реального кода для тестирования.Опять же, это предполагает, что вы все делаете правильно.

Если вам действительно нужна более сложная логика, то у вас должен быть класс, который имеет этот простой класс обслуживания в качестве зависимости, и сложная логика должна идти туда.Ваш класс обслуживания может реализовать интерфейс, так что вам будет полезно перейти к этому моменту.

Вы, конечно, можете провести интеграционное тестирование в своем классе обслуживания, который гарантировал бы, что он функционирует должным образом, фактически вызывая API или факсимильный аппарат.

1 голос
/ 10 июня 2019

Я не понимаю, что вы имеете в виду под

http-типизированным клиентом

, но если, как в примере, вы хотите протестировать класс, который использует HttpClient,Либо вы создаете оболочку для HttpClient и передаете его интерфейс, используя внедрение зависимостей (чтобы вы могли его смутить), либо вы используете параметр конструктора HttpResponseMessage в HttpClient.

Делаете HttpClient конструктороми в тесте создайте код, подобный следующему:

var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
   .Setup<Task<HttpResponseMessage>>(
      "SendAsync",
      ItExpr.IsAny<HttpRequestMessage>(), // Customise this as you want
      ItExpr.IsAny<CancellationToken>()
   )
   // Create the response you want to return
   .ReturnsAsync(new HttpResponseMessage()
   {    
      StatusCode = HttpStatusCode.OK,
      Content = new StringContent("[{'prop1': 100,'prop2': 'value'}]"),
   });

// Create an HttpClient using the mocked message handler
var httpClient = new HttpClient(mockHttpMessageHandler.Object)
{
   BaseAddress = new Uri("http://anyurl.com/"),
};

var testedService = new MyServiceUnderTest(httpClient);

var result = await testedService.MethodUnderTest(parameters [...]);

Чтобы упростить настройку moq, ограничивая ожидаемое HttpRequestMessage, я использую этот вспомогательный метод.

    /// <summary>
    /// Setup the mocked http handler with the specified criteria
    /// </summary>
    /// <param name="httpStatusCode">Desired status code returned in the response</param>
    /// <param name="jsonResponse">Desired Json response</param>
    /// <param name="httpMethod">Post, Get, Put ...</param>
    /// <param name="uriSelector">Function used to filter the uri for which the setup must be applied</param>
    /// <param name="bodySelector">Function used to filter the body of the requests for which the setup must be applied</param>
    private void SetupHttpMock(HttpStatusCode httpStatusCode, string jsonResponse, HttpMethod httpMethod, Func<string, bool> uriSelector, Func<string, bool> bodySelector = null)
    {
        if (uriSelector == null) uriSelector = (s) => true;
        if (bodySelector == null) bodySelector = (s) => true;

        _messageHandlerMock
            .Protected()
            .Setup<Task<HttpResponseMessage>>("SendAsync",
                ItExpr.Is<HttpRequestMessage>(m =>
                    m.Method == httpMethod &&
                    bodySelector(m.Content.ReadAsStringAsync().Result) &&
                    uriSelector(m.RequestUri.ToString())),
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = httpStatusCode,
                Content = jsonResponse == null ? null : new StringContent(jsonResponse, Encoding.UTF8, "application/json")
            });
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...