【问题标题】:Inject HttpClient from WebApplicationFactory从 WebApplicationFactory 注入 HttpClient
【发布时间】:2021-12-28 07:49:35
【问题描述】:

我正在尝试创建一个(大部分)统一的集成测试集,可以针对从 WebApplicationFactory 创建的内存 API 或我们应用程序的完全部署版本。使用XUnit.DependencyInjection,我计划将HttpClient 注入到我的测试中,它可以指向测试服务器或基于环境变量的真实应用程序。

所以要为测试服务器创建一个客户端,我可以在Startup.cs 中运行以下命令:

WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();

这似乎有效。但是,我完全不知道如何将 HttpClient 的这个实现注入到各个测试类中。

这样的东西,不起作用(这样的重载不存在):

services.AddHttpClient<MyTestClass>(client);

这也不是(注入的客户端由于某种原因将BaseAddress设置为null):

services.AddHttpClient<InMemoryServerSelfTests>(c =>
                                    {
                                        c.BaseAddress           = client.BaseAddress;
                                        c.Timeout               = client.Timeout;
                                    });

我唯一的另一个想法是创建一个包装两个客户端的新类并注入它,但这看起来很混乱:

public class TestClientWrapper
{
    public readonly HttpClient Client;
    public TestClientWrapper(InMemoryTestServer server)
    {
        Client = server.CreateClient();
    }

    public TestClientWrapper(HttpClient client)
    {
        Client = client;
    }
}

// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    string targetEndpoint = Environment.GetEnvironmentVariable("targetEndpoint"); // Make this configurable
    bool   isLocal        = string.IsNullOrEmpty(targetEndpoint);
    
    if (isLocal)
    {
        InMemoryTestServer app = new();
        services.AddSingleton(new TestClientWrapper(app));
    }
    else
    {
        HttpClient client = new();
        services.AddSingleton(new TestClientWrapper(client));
    }
}

所以说真的,我有点难过...关于如何实现这一点的任何想法?

【问题讨论】:

    标签: c# asp.net dependency-injection dotnet-httpclient


    【解决方案1】:

    问题在于WebApplicationFactory 生成的HttpClient 是特殊的,因为WebApplicationFactory 托管在内存中并且在进程外不可见(我认为这是我在其他地方读到的)。这意味着复制设置不起作用。

    我设法让WebApplicationFactory 客户端注册以使其可解析的唯一方法是使用从WebApplicationFactory 返回客户端的容器注册IHttpClientFactory 的实例。

    class TestClientFactory : IHttpClientFactory
    {
        WebApplicationFactory<Startup> _appFactory;
    
        public TestClientFactory(TestClientFactory _appFactory) => this._appFactory= appFactory;
    
        public HttpClient CreateClient(string name) => this._appFactory.CreateClient();
    }
    
    services.AddSingleton<IHttpClientFactory>(new TestClientFactory(...));
    

    类似的东西会起作用。

    【讨论】:

    • 我实际上使用了包装器,效果很好。然后我意识到我的 XUnit DI 有点废话,所以我现在正在使用 CollectionFixtures,其中包含必要的客户端和 web 应用程序......不过,这是一个很好的解决方案,所以谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多