Как смоделировать новый HttpClientFactory в .NET Core 2.1, используя Moq - PullRequest
0 голосов
/ 17 января 2019

.NET Core 2.1 поставляется с этой новой фабрикой под названием HTTPClientFactory, но я не могу понять, как смоделировать его для модульного тестирования некоторых методов, которые включают вызовы службы REST.

Фабрика вводится с использованием контейнера .NET Core IoC, и метод создает нового клиента из фабрики:

var client = _httpClientFactory.CreateClient();

А затем с помощью клиента получить данные из службы REST:

var result = await client.GetStringAsync(url);

Ответы [ 2 ]

0 голосов
/ 16 мая 2019

Этот код бросил это исключение для меня, System.InvalidOperationException: у запроса нет связанного объекта конфигурации, или предоставленная конфигурация была нулевой.

Так что включили это в метод испытания, и оно работает.

var configuration = new HttpConfiguration();
var request = new HttpRequestMessage();
request.SetConfiguration(configuration);
0 голосов
/ 17 января 2019

HttpClientFactory является производным от IHttpClientFactory Интерфейс Так что это просто вопрос создания макета интерфейса

var mockFactory = new Mock<IHttpClientFactory>();

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

Однако для этого требуется фактический HttpClient.

var clientHandlerStub = new DelegatingHandlerStub();
var client = new HttpClient(clientHandlerStub);

mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);

IHttpClientFactory factory = mockFactory.Object;

Завод может быть введен в зависимую систему при проведении теста.

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

Пример заглушки обработчика, используемой для подделки запросов

public class DelegatingHandlerStub : DelegatingHandler {
    private readonly Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> _handlerFunc;
    public DelegatingHandlerStub() {
        _handlerFunc = (request, cancellationToken) => Task.FromResult(request.CreateResponse(HttpStatusCode.OK));
    }

    public DelegatingHandlerStub(Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> handlerFunc) {
        _handlerFunc = handlerFunc;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _handlerFunc(request, cancellationToken);
    }
}

Взято из ответа, который я дал здесь

Ссылка Макет HttpClient с использованием Moq

Предположим, у вас есть контроллер

[Route("api/[controller]")]
public class ValuesController : Controller {
    private readonly IHttpClientFactory _httpClientFactory;

    public ValuesController(IHttpClientFactory httpClientFactory) {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet]
    public async Task<IActionResult> Get() {
        var client = _httpClientFactory.CreateClient();
        var url = "http://example.com";
        var result = await client.GetStringAsync(url);
        return Ok(result);
    }
}

и хотел проверить действие Get().

public async Task Should_Return_Ok() {
    //Arrange
    var expected = "Hello World";
    var mockFactory = new Mock<IHttpClientFactory>();
    var configuration = new HttpConfiguration();
    var clientHandlerStub = new DelegatingHandlerStub((request, cancellationToken) => {
        request.SetConfiguration(configuration);
        var response = request.CreateResponse(HttpStatusCode.OK, expected);
        return Task.FromResult(response);
    });
    var client = new HttpClient(clientHandlerStub);

    mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);

    IHttpClientFactory factory = mockFactory.Object;

    var controller = new ValuesController(factory);

    //Act
    var result = await controller.Get();

    //Assert
    result.Should().NotBeNull();

    var okResult = result as OkObjectResult;

    var actual = (string) okResult.Value;

    actual.Should().Be(expected);
}
...