我的代码使用HttpClient来检索一些数据
HttpClient client = new HttpClient
{
BaseAddress = new Uri("myurl.com"),
};
var msg = new HttpRequestMessage(HttpMethod.Get, "myendpoint");
var res = await client.SendAsync(msg);我如何在HttpClient上模拟这个HttpClient方法并将其注入.net核心ServiceCollection中?
我试着像这样嘲弄
var mockFactory = new Mock<IHttpClientFactory>();
var mockHttpMessageHandler = new Mock<HttpMessageHandler>();
mockHttpMessageHandler.Protected()
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("{'name':thecodebuzz,'city':'USA'}"),
});
var client = new HttpClient(mockHttpMessageHandler.Object);
mockFactory.Setup(_ => _.CreateClient(It.IsAny<string>())).Returns(client);但是如何将这个mockFactory注入ServiceCollection呢?或者也许有更简单的或不同的方法?
发布于 2021-09-07 17:40:06
为什么不对HTTP调用进行封装,而不是模拟它呢?然后您可以模拟封装/抽象。
例如:
interface IClient
{
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default);
}
class HttpClientAdapter : IClient
{
readonly HttpClient _client;
public HttpClientAdapter(HttpClient client)
{
_client = client;
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default) => _client.SendAsync(request, cancellationToken);
}使您的代码依赖于IClient接口。在正常使用期间,您将在HttpClient实现中使用真正的HttpClientAdapter。对于测试,您可以模拟IClient。
注意,将抽象级别提高一点对您可能更有用。例如,如果您希望将来自HTTP响应的JSON字符串解析为某些DataObject,那么您的IClient接口应该更像这样:
class DataObject
{
public string Name { get; set; }
public string City { get; set; }
}
interface IClient
{
Task<DataObject> GetAsync(CancellationToken cancellationToken = default);
}
public class ClientImplementation : IClient
{
readonly HttpClient _client;
public ClientImplementation(HttpClient client)
{
_client = client;
}
public async Task<DataObject> GetAsync(CancellationToken cancellationToken = default)
{
var response = await _client.SendAsync(...);
var dataObject = new DataObject();
// parse the response into the data object
return dataObject;
}
}在这里划定界限的好处是您的测试将有较少的工作要做。例如,您的模拟代码不必设置HttpResponseMessage对象。
你选择在哪里为你的抽象划定界限完全取决于你自己。但关键是:一旦代码依赖于一个小接口,那么就很容易模拟该接口并测试您的代码。
发布于 2021-09-07 16:41:01
如果您真的需要模拟HttpClient本身,请看下面的lib:https://github.com/richardszalay/mockhttp
从医生那里:
var mockHttp = new MockHttpMessageHandler();
// Setup a respond for the user api (including a wildcard in the URL)
mockHttp.When("http://localhost/api/user/*")
.Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON
// Inject the handler or client into your application code
var client = mockHttp.ToHttpClient();
var response = await client.GetAsync("http://localhost/api/user/1234");
// or without async: var response = client.GetAsync("http://localhost/api/user/1234").Result;
var json = await response.Content.ReadAsStringAsync();
// No network connection required
Console.Write(json); // {'name' : 'Test McGee'}https://stackoverflow.com/questions/69091529
复制相似问题