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