从 WebApplicationFactory 注入 HttpClient
Inject HttpClient from WebApplicationFactory
我正在尝试创建(大部分)统一的集成测试集,这些测试可以针对从 WebApplicationFactory
创建的内存中 API 或完全部署的版本我们的应用程序。使用 XUnit.DependencyInjection
,我计划在我的测试中注入一个 HttpClient
,它指向测试服务器或基于环境变量的真实应用程序。
所以要为测试服务器创建一个客户端,我可以 运行 Startup.cs
中的以下内容:
WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();
这似乎有效。但是,我完全不知道如何将 HttpClient
的这个实现注入到单独的测试 classes.
像这样的东西不起作用(这样的重载不存在):
services.AddHttpClient<MyTestClass>(client);
这也不行(注入的客户端出于某种原因将 BaseAddress
设置为 null):
services.AddHttpClient<InMemoryServerSelfTests>(c =>
{
c.BaseAddress = client.BaseAddress;
c.Timeout = client.Timeout;
});
我唯一的其他想法是创建一个新的 class 来包装两个客户端并注入它,但这看起来很乱:
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));
}
}
真的,我有点难过...关于如何完成这个的任何想法?
问题是 WebApplicationFactory
生成的 HttpClient
是特殊的,因为 WebApplicationFactory
托管在内存中并且在进程外不可见(我想这就是我读到的别处)。这意味着复制设置不起作用。
我设法让 WebApplicationFactory
客户端注册以使其可解析的唯一方法是向 returns 客户端的容器注册 IHttpClientFactory
的实例WebApplicationFactory
.
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(...));
按照这些思路行事。
我正在尝试创建(大部分)统一的集成测试集,这些测试可以针对从 WebApplicationFactory
创建的内存中 API 或完全部署的版本我们的应用程序。使用 XUnit.DependencyInjection
,我计划在我的测试中注入一个 HttpClient
,它指向测试服务器或基于环境变量的真实应用程序。
所以要为测试服务器创建一个客户端,我可以 运行 Startup.cs
中的以下内容:
WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();
这似乎有效。但是,我完全不知道如何将 HttpClient
的这个实现注入到单独的测试 classes.
像这样的东西不起作用(这样的重载不存在):
services.AddHttpClient<MyTestClass>(client);
这也不行(注入的客户端出于某种原因将 BaseAddress
设置为 null):
services.AddHttpClient<InMemoryServerSelfTests>(c =>
{
c.BaseAddress = client.BaseAddress;
c.Timeout = client.Timeout;
});
我唯一的其他想法是创建一个新的 class 来包装两个客户端并注入它,但这看起来很乱:
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));
}
}
真的,我有点难过...关于如何完成这个的任何想法?
问题是 WebApplicationFactory
生成的 HttpClient
是特殊的,因为 WebApplicationFactory
托管在内存中并且在进程外不可见(我想这就是我读到的别处)。这意味着复制设置不起作用。
我设法让 WebApplicationFactory
客户端注册以使其可解析的唯一方法是向 returns 客户端的容器注册 IHttpClientFactory
的实例WebApplicationFactory
.
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(...));
按照这些思路行事。