Per*_*nce 4 c# asp.net dependency-injection dotnet-httpclient
WebApplicationFactory
我正在尝试创建一组(大部分)统一的集成测试,这些测试可以针对从我们的应用程序的完全部署版本创建的内存中 API 。使用XUnit.DependencyInjection
,我计划将 a 注入HttpClient
到我的测试中,该测试要么指向测试服务器,要么基于环境变量指向真实的应用程序。
因此,要为测试服务器创建客户端,我可以在以下位置运行以下命令Startup.cs
:
WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();
Run Code Online (Sandbox Code Playgroud)
这似乎有效。但是,我完全不知道如何将此实现注入到HttpClient
各个测试类中。
像这样的东西不起作用(这样的重载不存在):
services.AddHttpClient<MyTestClass>(client);
Run Code Online (Sandbox Code Playgroud)
这也不是(注入的客户端BaseAddress
由于某种原因设置为 null):
services.AddHttpClient<InMemoryServerSelfTests>(c =>
{
c.BaseAddress = client.BaseAddress;
c.Timeout = client.Timeout;
});
Run Code Online (Sandbox Code Playgroud)
我唯一的另一个想法是创建一个新类来包装两个客户端并注入它,但这看起来很混乱:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
所以真的,我有点难住了......关于如何实现这一目标有什么想法吗?
问题是HttpClient
生成的WebApplicationFactory
是特殊的,因为WebApplicationFactory
托管在内存中并且在进程外不可见(我认为这是我在其他地方读到的)。这意味着复制设置不起作用。
我设法WebApplicationFactory
注册客户端以使其可解析的唯一方法是向IHttpClientFactory
从WebApplicationFactory
.
public class TestHttpClientFactory<TStartup> : IHttpClientFactory
where TStartup : class
{
private readonly WebApplicationFactory<TStartup> _appFactory;
public TestHttpClientFactory(WebApplicationFactory<TStartup> appFactory) => _appFactory = appFactory;
public HttpClient CreateClient(string name) => _appFactory.CreateClient();
}
Run Code Online (Sandbox Code Playgroud)
services.AddSingleton<IHttpClientFactory>(new TestClientFactory(...));
Run Code Online (Sandbox Code Playgroud)
沿着这些思路的一些东西将会起作用。