首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟HttpClient SendAsync方法

模拟HttpClient SendAsync方法
EN

Stack Overflow用户
提问于 2021-09-07 16:14:10
回答 2查看 865关注 0票数 2

我的代码使用HttpClient来检索一些数据

代码语言:javascript
复制
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中?

我试着像这样嘲弄

代码语言:javascript
复制
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呢?或者也许有更简单的或不同的方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-07 17:40:06

为什么不对HTTP调用进行封装,而不是模拟它呢?然后您可以模拟封装/抽象。

例如:

代码语言:javascript
复制
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接口应该更像这样:

代码语言:javascript
复制
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对象。

你选择在哪里为你的抽象划定界限完全取决于你自己。但关键是:一旦代码依赖于一个小接口,那么就很容易模拟该接口并测试您的代码。

票数 2
EN

Stack Overflow用户

发布于 2021-09-07 16:41:01

如果您真的需要模拟HttpClient本身,请看下面的lib:https://github.com/richardszalay/mockhttp

从医生那里:

代码语言:javascript
复制
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'}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69091529

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档