'IClassFixture called multipletimes with locked Simple Injector Container

i'm trying to test my controllers with IClassFixture<WebApplicationFactory<Startup>>, but when i run multiples tests i get the error:

System.InvalidOperationException : The container can't be changed after the first call to GetInstance, GetAllInstances, Verify, and some calls of GetRegistration. Please see https://simpleinjector.org/locked to understand why the container is locked. The following stack trace describes the location where the container was locked:

public class TestControllerTests : IClassFixture<WebApplicationFactory<Startup>>
{
    private readonly HttpClient _httpClient;
    private readonly TestDbContext _dbContext;
    private readonly AuthenticationClientBuilder<MicrosoftPatternAdministratorAuthHandler, Startup> _builder;
    private readonly WebApplicationFactory<Startup> _factory;
    public LicenseControllerTests(WebApplicationFactory<Startup> factory)
    {
        _factory = factory;
        _builder = new AuthenticationClientBuilder<MicrosoftPatternAdministratorAuthHandler, Startup>();
            
        _dbContext = new TestDbContext(new DbContextOptions<TestDbContext>());
        _dbContext.Database.SetConnectionString(_builder.GetConnectionString());

        DbInitializer.Initialize(_dbContext);
        _httpClient = _builder.BuildAuthenticatedClient(_factory);
    }
}

In the callstack, i see that the error ocourred in the line: _httpClient = _builder.BuildAuthenticatedClient(_factory);

The code of this class is:

namespace Namespace_X
{
    public class AuthenticationClientBuilder<TAuthenticationHandler, TStartup> : IDisposable
        where TAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
        where TStartup : class
    {
        private WebApplicationFactory<TStartup> _factory;
        private readonly string _connectionString;
        public AuthenticationClientBuilder()
        {
            var config = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .Build();

            _connectionString = config["AppSettings:ConnectionString"];
        }

        public HttpClient BuildAuthenticatedClient(WebApplicationFactory<TStartup> factory)
        {
            _factory = factory;

            return _factory.WithWebHostBuilder(builder =>
            {
                builder.ConfigureTestServices(services =>
                {
                    services.AddAuthentication("TestAuthentication")
                            .AddScheme<AuthenticationSchemeOptions, TAuthenticationHandler>("TestAuthentication", null);


                    var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(TestDbContext));
                    if (descriptor != null)
                    {
                        services.Remove(descriptor);
                        services.AddDbContext<TestDbContext>((options, context) =>
                        {
                            context.UseSqlServer(_connectionString);
                        });
                    }
                });
            }).CreateClient();
        }

        public string GetConnectionString()
        {
            return _connectionString;
        }

        public void Dispose()
        {
            _factory.Dispose();
        }
    }
}

In the startup the exception is throw when the container try to register the DbContext:

container.Register(() =>
{
    var options = new DbContextOptionsBuilder<TestDbContext>().UseSqlServer().Options;

    return new TestDbContext(options);

}, Lifestyle.Transient);

When i run one test per time they work.

Any hint? Thx in advance



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source