I'm trying to create a (mostly) unified set of integation tests that can either be targetted at an in-memory API created from a WebApplicationFactory or at a fully-deployed version of our app. Using XUnit.DependencyInjection, I'm planning on injecting a HttpClient into my tests that either points to the test server or the real app based on an environment variable.
So to create a client for the test server, I can just run the following in Startup.cs:
WebApplicationFactory<Program> app = new();
HttpClient client = app.CreateClient();
This seems to work. However, I have absolutely no idea how to inject this implementation for the HttpClient into the individual test classes.
Something like this, doesn't work (such an overload doesn't exist):
services.AddHttpClient<MyTestClass>(client);
And neither does this (the injected client has the BaseAddress set to null for some reason):
services.AddHttpClient<InMemoryServerSelfTests>(c =>
{
c.BaseAddress = client.BaseAddress;
c.Timeout = client.Timeout;
});
My only other thought is to create a new class that wraps both clients and inject that instead but that seems messy:
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));
}
}
So really, I'm a bit stumped... Any ideas on how to accomplish this?