c# - 使用特定的 HttpMessageHandler 注入(inject)单实例 HttpClient

标签 c# asp.net-core asp.net-core-mvc .net-core dotnet-httpclient

作为我正在处理的 ASP.Net Core 项目的一部分,我需要从我的 WebApi 中与许多不同的基于 Rest 的 API 端点进行通信。为了实现这一点,我使用了许多服务类,每个服务类都实例化一个静态 HttpClient .本质上,我为 WebApi 连接到的每个基于 Rest 的端点都有一个服务类。

如何静态的例子HttpClient在每个服务类中实例化如下所示。

private static HttpClient _client = new HttpClient()
{
    BaseAddress = new Uri("http://endpointurlexample"),            
};

虽然上面的方法运行良好,但它不允许对使用 HttpClient 的服务类进行有效的单元测试。 .为了使我能够进行单元测试,我有一个假的 HttpMessageHandler我想用于 HttpClient在我的单元测试中,同时 HttpClient如上所述实例化但是我无法应用假 HttpMessageHandler作为我的单元测试的一部分。

HttpClient 的最佳方式是什么?在服务类中在整个应用程序中保持单个实例(每个端点一个实例),但允许不同的 HttpMessageHandler在单元测试期间应用?

我想到的一种方法是不使用静态字段来保存 HttpClient在服务类中,而不是允许它使用单例生命周期通过构造函数注入(inject)来注入(inject),这将允许我指定一个 HttpClient与所需的 HttpMessageHandler在单元测试期间,我想到的另一个选择是使用 HttpClient实例化 HttpClient 的工厂类s 在静态字段中,然后可以通过注入(inject) HttpClient 来检索工厂进入服务类,再次允许与相关的不同实现 HttpMessageHandler在单元测试中返回。但是,以上都不是特别干净,感觉必须有更好的方法?

有任何问题,请告诉我。

最佳答案

添加到评论中的对话看起来您需要一个 HttpClient 工厂

public interface IHttpClientFactory {
    HttpClient Create(string endpoint);
}

核心功能的实现可能看起来像这样。

public class DefaultHttpClientFactory : IHttpClientFactory, IDisposable
{
    private readonly ConcurrentDictionary<string, HttpClient> _httpClients;

    public DefaultHttpClientFactory()
    {
        this._httpClients = new ConcurrentDictionary<string, HttpClient>();
    }

    public HttpClient Create(string endpoint)
    {
        if (this._httpClients.TryGetValue(endpoint, out var client))
        {
            return client;
        }

        client = new HttpClient
        {
            BaseAddress = new Uri(endpoint),
        };

        this._httpClients.TryAdd(endpoint, client);

        return client;
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        foreach (var httpClient in this._httpClients)
        {
            httpClient.Value.Dispose();
        }
    }
}

也就是说,如果您对上述设计不是特别满意。您可以抽象出服务背后的 HttpClient 依赖性,这样客户端就不会成为实现细节。

服务的消费者不需要确切地知道数据是如何检索的。

关于c# - 使用特定的 HttpMessageHandler 注入(inject)单实例 HttpClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43118874/

相关文章:

c# - 如何隐藏红隼控制台?

c# - Controller 位于区域中的 RedirectToAction

c# - Web API 帖子正文属性 null

c# - 为什么我会收到以下错误?无效的方差修饰符。只有接口(interface)和委托(delegate)类型参数可以指定为变体

c# - 使用 c# 列出来自 mysql 服务器的所有数据库

asp.net-core - 返回404页面,无需重定向

asp.net - asp mvc 6 中的 token 身份验证

c# - 如何创建一个 web Api 具有 http post 功能,它可以从正文中获取任何动态 json 内容并能够将其解析为字符串

asp.net-core - 动态创建和销毁 Blazor 客户端组件?

sql-server - 使用 EF Core 从数据库获取数据时忽略实体的额外属性