Override EF Core DbContext in ASP.NET Core WebApplicationFactory
Asked Answered
G

1

14

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.

Glandular answered 14/10, 2019 at 11:9 Comment(3)
Can you publish DbContext (Constructor and OnConfigure)?Baptize
You could try services.RemoveAll(typeof(DbContextOptions<MyContext>));.Peoria
Or services.RemoveAll<DbContextOptions<MyContext>>();Scalise
H
34

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();
Hippel answered 24/12, 2019 at 2:32 Comment(2)
nowadays you can just services.RemoveAll(typeof(DbContextOptions<UserProfilesDbContext>));Variola
Do not use "options.UseInMemoryDatabase". That way you are not testing your real scenarion. Use your real DB provider instead: options.UseSqlServer or options.UseMySql.Hemangioma

© 2022 - 2024 — McMap. All rights reserved.