问题描述
.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
假设你有一个控制器
[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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!