`WebApplicationFactory` and methods in `Program.Main` that should only be called once
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
Hi, I am migrating my AspNetCore app from an older version that utilized `Startup.cs` and `.UseStartup()` to a newer version that uses `WebApplicationBuilder` and related patterns.
I've encountered an issue when migrating integration tests that use `WebApplicationFactory`.
Before migration, `WebApplicationFactory` used `CreateHostBuilder` to configure DI services and request processing pipeline.
After migration to `WebApplicationBuilder` - the `WebApplicationFactory` now uses `Program.Main` to configure everything, which results in additional code being executed compared to the previous version.
The issue comes from a third-party library I am using.
It needs to be initialized by calling some static methods as soon as the app starts, before any other classes from this library are utilized in DI etc.
This method can only be called once, and any subsequent calls result in it throwing an exception.
When I run my tests - they fail because the initialization methods are called multiple times.
Ideally, I don't want this code to run at all and only want to run the code that configures the DI and request processing pipeline, similar to how it worked before.
I will attach some pseudo-code, to hopefully better explain the issue:
```cs
public class ThirdPartyLibrary
{
static readonly Lock _lock = new();
static bool isInitialized = false;
public static void Init()
{
lock (_lock)
{
if (isInitialized) throw new Exception("you called this twice");
isInitialized = true;
}
}
}
public class Program
{
public static void Main(string[] args)
{
ThirdPartyLibrary.Init();
var builder = WebApplication.CreateBuilder(args);
var startup = new Startup();
startup.ConfigureServices(builder.Services);
var app = builder.Build();
startup.Configure(app);
app.Run();
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services.AddControllers();
public void Configure(WebApplication app) => app.MapControllers();
}
```
I can wrap this code into my own lock and add a boolean flag to ensure it only runs once, but that does not seem like a good solution.
What is the recommended pattern to use in this scenario?
Ideally, I would like to avoid executing the entire `Main` and only call `ConfigureServices` and `Configure` for the request pipeline, similar to how it was before.
Contributor guide
Assessment
This issue has not been assessed yet.