Search code examples
c#asp.net-coreentity-framework-coreasp.net-core-3.0entity-framework-core-3.0

Override EF Core DbContext in ASP.NET Core WebApplicationFactory


I have a ASP.NET Core 2.2 WebApi project which uses also EF Core 2.2. The project is tested via integration tests with WebApplicationFactory<T>.

I tried to migrate the the web api project to netcore/aspnetcore 3 which worked out very well. What I've stumbled across is migrating the tests.

I have following code which worked in aspnetcore 2.2:

    public class MyServiceWebHostFactory : WebApplicationFactory<Service.Startup>
    {
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {   
            builder.ConfigureServices(services =>
            {
                var serviceProvider = new ServiceCollection()
                                   .AddEntityFrameworkInMemoryDatabase()
                                   .BuildServiceProvider();

                services.AddDbContext<MyContext>((options, context) =>
                {
                    context.UseInMemoryDatabase("MyDb")
                           .UseInternalServiceProvider(serviceProvider);
                });

                var sp = services.BuildServiceProvider();

                using var scope = sp.CreateScope();

                var scopedServices = scope.ServiceProvider;

                // try to receive context with inmemory provider:
                var db = scopedServices.GetRequiredService<MyContext>();

                // more code...

                // Ensure the database is created.
                //db.Database.EnsureCreated();

                // more code...
            });
        }
    }

It replaces the EF Core DbContext with a DbContext using the InMemoryProvider.

After migrating to 3.0 it isn't replaced anymore. I always receive the DBContext with SQL Server configured.

If I remove the services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString)) call in ConfigureServices of the application (Service.Startup) it works but this isn't a solution.

I also tried a services.RemoveAll(typeof(MyContext)) before registering the inmemory context which doesn't work either.


Solution

  • The updated documentation at https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1 might be able to help. Key fragment change is to remove the previous context service registration:

    // Remove the app's ApplicationDbContext registration.
    var descriptor = services.SingleOrDefault(
        d => d.ServiceType ==
            typeof(DbContextOptions<ApplicationDbContext>));
    
    if (descriptor != null)
    {
        services.Remove(descriptor);
    }
    
    // Add ApplicationDbContext using an in-memory database for testing.
    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.UseInMemoryDatabase("InMemoryDbForTesting");
    });
    
    // Build the service provider.
    var sp = services.BuildServiceProvider();