httpclient - 如何在 C# 中包装 HttpClient 以实现可测试性

标签 httpclient asp.net-web-api

我正在调用一个外部 API,并希望我的 API 可以进行单元测试。为此,我正在尝试包装 HttpClient。我现在只需要一种方法。
这是我的界面。

public interface IHttpClient
{
    Task<string> GetStringAsync(string url);
}

这就是我实现它的方式。

公共(public)类 HttpClientWrapper : IHttpClient
{
私有(private)只读 HttpClient _httpClient;
    public HttpClientWrapper()
    {
        // I could also inject this but I think this will be fine as is. 
        _httpClient = new HttpClient(new HttpClientHandler(), false);
    }

    public async Task<string> GetStringAsync(string url)
    {
        //validate url here
        return await _httpClient.GetStringAsync(url);
    }

}

我有疑问吗?这是正确的方法吗?设置 bool 参数会导致这里的资源泄漏吗?我阅读了一些关于是否必须在每次调用时处理 HttpClient 的相互矛盾的想法。我接受了,不处理的一面,但不是很确定。
如果有一种方法可以在没有包装器的情况下使用 HttpClient 但使 API 可测试,那也很棒。但到目前为止,我未能让它发挥作用。

谢谢,
清洁科德

最佳答案

虽然为客户端创建一个界面还是不错的,但 HttpClient类实际上是在考虑可测试性的情况下设计的!实例化您的 HttpClient 时您可以注入(inject)自定义 HttpMessageHandler .通过覆盖 Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)在此类中,您可以在所有请求实际写入套接字之前中断所有请求,检查它们并返回您认为合适的任何内容。

这是我在一个项目中编写的这样一个测试替身的示例,您可以随意修改它以满足您的需求:

public class FakeHttpMessageHandler : HttpMessageHandler
{
    public HttpRequestMessage LastRequest;
    public string LastRequestString = string.Empty;
    public string ResponseContent = string.Empty;
    public HttpStatusCode ResponseStatusCode = HttpStatusCode.OK;

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        if (request.Content != null)
        {
            LastRequestString = await request.Content.ReadAsStringAsync();
        }
        LastRequest = request;
        return await Task.FromResult(new HttpResponseMessage
        {
            StatusCode = ResponseStatusCode,
            Content = new StringContent(ResponseContent)
        });
    }
}

如果您认为这更适合您的项目,您也可以使用一些隔离框架,例如 NSubstitute。

关于httpclient - 如何在 C# 中包装 HttpClient 以实现可测试性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24643523/

相关文章:

asp.net-web-api - 如何使用visual fox pro的 Restful 服务?

java - eXistDB 5.2.0 版本没有httpclient?

.net - 依赖注入(inject) - 何时在 Web 应用程序中使用单例范围

PHP GuzzleHttp。如何使用参数发出 post 请求?

GoLang - 遵循带有正文数据的 POST 请求的重定向

c# - Web api 以错误的格式发送 JSON 对象

asp.net - Asp.Net Web API 的默认 header 值 "Accept"

asp.net-web-api - 如何在 IIS 托管的 ASP.NET Web API (v1) 中配置 MaxReceivedMessageSize?

java - 如何使 Apache Commons HttpClient 3.1 忽略 HTTPS 证书无效?

Angular 4 : How to set params with HttpParams?