本文介绍了如何使用 Moq 在 .NET Core 2.1 中模拟新的 HttpClientFactory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET Core 2.1 附带了这个名为 HttpClientFactory 的新工厂,但我不知道如何模拟它以对一些包括 REST 服务调用的方法进行单元测试.

.NET Core 2.1 comes with this new factory called HttpClientFactory, but I can't figure out how to mock it to unit test some methods that include REST service calls.

工厂正在使用 .NET Core IoC 容器注入,该方法的作用是从工厂创建一个新客户端:

The factory is being injected using .NET Core IoC container, and what the method does is create a new client from the factory:

var client = _httpClientFactory.CreateClient();

然后使用客户端从 REST 服务中获取数据:

And then using the client to get data from a REST service:

var result = await client.GetStringAsync(url);

推荐答案

HttpClientFactory 派生自 IHttpClientFactory 接口 所以这只是一个创建接口模拟的问题

The HttpClientFactory is derived from IHttpClientFactory Interface So it is just a matter of creating a mock of the interface

var mockFactory = new Mock<IHttpClientFactory>();

根据您需要客户端的用途,您需要设置模拟以返回 HttpClient 用于测试.

Depending on what you need the client for, you would then need to setup the mock to return a HttpClient for the test.

然而这需要一个实际的HttpClient.

This however requires an actual HttpClient.

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

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

IHttpClientFactory factory = mockFactory.Object;

然后可以在执行测试时将工厂注入到被测依赖系统中.

The factory can then be injected into the dependent system under test when exercising the test.

如果您不希望客户端调用实际端点,那么您将需要创建一个假委托处理程序来拦截请求.

If you do not want the client calling actual endpoints then you will need to create a fake delegate handler to intercept the requests.

用于伪造请求的处理程序存根示例

Example of the handler stub used to fake the requests

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);
    }
}

摘自我在这里给出的答案

Taken from an answer I gave here

参考 使用 Moq 模拟 HttpClient

假设你有一个控制器

[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);
}

这篇关于如何使用 Moq 在 .NET Core 2.1 中模拟新的 HttpClientFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 23:55