Макет HttpClientFactory для создания макета HttpClient с использованием Moq Framework - PullRequest
2 голосов
/ 17 июня 2019

У меня есть метод, который содержит HttpClientFactory, который создает HttpClient. Метод вызывает в нем метод SendAsync. Мне нужно манипулировать методом SendAsync, чтобы отправить мне сообщение об успешном завершении, что бы оно ни использовало в качестве аргумента.

Я хочу проверить этот метод

public class TestService
{
    private readonly IHttpClientFactory _clientFactory;

    public TestService(IHttpClientFactory clientFactory)
    {
         _clientFactory = clientFactory;
    }

    public async Task<bool> TestMethod(string testdata)
    {
        var message = new HttpRequestMessage(); //SIMPLIFIED CODE
        var client = _clientFactory.CreateClient();
        var response = await client.SendAsync(message);

        if(response.IsSuccessStatusCode){
            return true;
        }else{
            return false;
        }
    }
}

Я пытаюсь

private readonly Mock<IHttpClientFactory> _mockHttpClientFactory;
private readonly Mock<HttpClient> _mockHttpClient;

[Fact]
public void TestMethod_ValidHttpRequest_ReturnsTrue()
{
    var httpClient = _mockHttpClient.Setup(x => x.SendAsync(It.IsAny<HttpRequestMessage>()))
                                        .ReturnsAsync(new HttpResponseMessage()
                                        {
                                            StatusCode = HttpStatusCode.OK,
                                            Content = new StringContent("[{'id':1,'value':'1'}]"),
                                        });

    var client = _mockHttpClientFactory.Setup(x => x.CreateClient()).Returns(httpClient); //DOESNT WORK

    var service = new TestService(_mockHttpClientFactory);
    var result = service.TestMethod("testdata");
    Assert.True(result.Result)
}

1 Ответ

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

Предлагаю заглянуть в следующий пост от Gingster Ale .Этот пример автора показывает вам, как вы можете имитировать вызовы HttpClient:

// 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, я рекомендую взглянуть на Flurl .

...