Как издеваться над httpclient - PullRequest
0 голосов
/ 15 мая 2019

Я новичок в TDD. Вы можете написать тестовый пример, используя moq для следующего кода -

public async Task<Model> GetAssetDeliveryRecordForId(string id)
    {
        var response = await client.GetAsync($"api/getdata?id={id}");

        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadAsAsync<Model>();

        return result;
    }

Заранее спасибо.

1 Ответ

2 голосов
/ 15 мая 2019

Вы можете использовать Moq, чтобы издеваться над ним.

Использование Moq для вас

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

Moq - это популярная библиотека .NET, которая помогает имитировать объекты для тестирования. По сути, он использует отражения и выражения для динамического генерирования макеты во время выполнения ваших тестов, основанные на спецификациях, которые вы объявлять с использованием свободного API.

Теперь здесь есть небольшая проблема. Как вы заметили, SendAsync метод на абстрактном классе HttpMessageHandler защищен. предостережение: Moq не может автоматически реализовать защищенные методы так просто с интерфейсами или публичными методами. Причина в том, что бегло API использует выражения на поддельном типе, и это не может предложить частный или защищенные члены, так как вы получаете доступ к классу снаружи здесь. Так, мы должны использовать некоторые более продвинутые функции Moq, чтобы макетировать наши защищенный метод здесь.

Поэтому у Moq есть API для этого. Вы используете Moq. Защищенный; в вашем используя пункты, а затем вы можете перейти на свой Moq с .Protected () метод. Это дает вам несколько дополнительных методов на Moq, где вы можете получить доступ к защищенным членам, используя их имена.

Полный тест класса с использованием HttpClient с использованием Moq будет выглядеть как это:

// ARRANGE
var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
handlerMock
   .Protected()
   // Setup the PROTECTED method to mock
   .Setup<Task<HttpResponseMessage>>(
      "SendAsync",
      ItExpr.IsAny<HttpRequestMessage>(),
      ItExpr.IsAny<CancellationToken>()
   )
   // prepare the expected response of the mocked http call
   .ReturnsAsync(new HttpResponseMessage()
   {
      StatusCode = HttpStatusCode.OK,
      Content = new StringContent("[{'id':1,'value':'1'}]"),
   })
   .Verifiable();

// use real http client with mocked handler here
var httpClient = new HttpClient(handlerMock.Object)
{
   BaseAddress = new Uri("http://test.com/"),
};

var subjectUnderTest = new MyTestClass(httpClient);

// ACT
var result = await subjectUnderTest
   .GetSomethingRemoteAsync('api/test/whatever');

// ASSERT
result.Should().NotBeNull(); // this is fluent assertions here...
result.Id.Should().Be(1);

// also check the 'http' call was like we expected it
var expectedUri = new Uri("http://test.com/api/test/whatever");

handlerMock.Protected().Verify(
   "SendAsync",
   Times.Exactly(1), // we expected a single external request
   ItExpr.Is<HttpRequestMessage>(req =>
      req.Method == HttpMethod.Get  // we expected a GET request
      && req.RequestUri == expectedUri // to this uri
   ),
   ItExpr.IsAny<CancellationToken>()
);

Для юнит-тестов вы не издеваетесь над HttpClient. Вместо этого вы издеваетесь HttpMessageHandler, поместите это в HttpClient и верните его все, что вы хотите таким образом. Если вы не хотите создавать конкретные Вывод HttpMessageHandler для каждого теста, вы также можете иметь Moq создать насмешки для вас автоматически.

Читать всю статью здесь .

...