Avoid external call for configuration when integraiton testing with WebApplication.CreateBuilder()

47 Views Asked by At

I'm implementing an Azure Container App that relies on a call with Dapr to get values from a Key Vault. This call is executed during application startup, but new DaprClientBuilder().Build() naturally fails when running in a WebApplicationFactory. I want to avoid this call when integration testing with WebApplicationFactory. I've tried numerous approaches but I'm stuck getting to a point where I can omit that external call during startup.

Program.cs goes like this

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddApplication();
builder.Services.AddInfrastructure(builder);
builder.Services.AddPresentation(builder);

builder.Configuration.AddDaprSecretStore("secrets", new DaprClientBuilder().Build());

var app = builder.Build();

Before when we had a Program and a Startup (before WebApplication.CreateBuilder()) it was easier to tap in the startup with WebApplicationFactory because host build and application build was split. It simply meant creating a new host in the factory, thus omitting the external calls, overriding ConfigreAppConfiguration() and adding test configuration here. But this approach is now invalid since host build up and application buildup is mixed in Program.cs. Therefore I cannot use .UseStartup<Program>().

Any ideas how to get around this?

1

There are 1 best solutions below

0
Guru Stron On

AFAIK not much can be done here. If I remember correctly then WebApplicationFactory uses some dirty magic (similar to one briefly described here for EF Core) to perform app setup which requires everything before builder.Build() to be executed.

You need to either migrate back to the generic hosting (the one with Startup's files, note that in theory you should be able to use environment specific Startup's with it) or perform custom initialization logic based on environment. For example (you can move it to some neatly encapsulated extension/Program method):

if (!builder.Environment.IsEnvironment("TEST"))
{
    builder.Configuration.AddDaprSecretStore("secrets", new DaprClientBuilder().Build());
}

And in the test:

var webApplicationFactory = new WebApplicationFactory<Program>();
webApplicationFactory = webApplicationFactory.WithWebHostBuilder(builder =>
{
    // ...
    builder.UseEnvironment("Test");
});

// use webApplicationFactory

Or via custom application factory:

public class CustomWebApplicationFactory<TProgram> : WebApplicationFactory<TProgram> where TProgram : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        // ...
        builder.UseEnvironment("Test");
    }
}