Skip to content

Not Able to UseInMemoryDatabase with WebApplicationFactory #14955

@OdeToCode

Description

@OdeToCode

This is related, I think, to the confusion expressed in dotnet/efcore#17224. No matter what I try, I cannot get an InMemoryDatabase into the service collection for an ASP.NET Core app. This was a scenario that was working by following the docs, but isn't working since I moved to 3.0.

Steps to reproduce

I'm using the code from this directory in my repository: https://github.com/OdeToCode/explore-aspnetcore/tree/master/All/test/TestTheTest

You should be able to download the folder and dotnet build / dotnet test the solution.

The idea is to run integration tests against an ASP.NET Core application by swapping out a DbContext configured to use SQL Server with a DbContext configured for in-memory. The web app configures services like so:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SomeDbContext>(options =>
    {
        options.UseSqlServer("fail");
    });
}

The tests use a custom WebApplicationFactory in an attempt to override the DbContext options.

public class CustomWebFactory : WebApplicationFactory<Startup>
{
    protected override IHostBuilder CreateHostBuilder()
    {
        return Host.CreateDefaultBuilder()
                   .ConfigureWebHostDefaults(c =>
                   {
                       c.UseStartup<Startup>();
                   });
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            services.AddDbContext<SomeDbContext>(options =>
            {
                options.UseInMemoryDatabase("DB");
            });
        });
    }
}

The test in the project uses a simple piece of middleware to look at the configured provider for the DbContext at runtime.

public async Task Invoke(HttpContext ctx, SomeDbContext db)
{
    if (ctx.Request.Path.StartsWithSegments("/db"))
    {
        await ctx.Response.WriteAsync(db.Database.ProviderName);
    }
    else
    {
        await next(ctx);
    }
}

I am able to override and change other services in the WebApplicationFactory, except for the DbContext options. The only technique that seems to work is to remove the call to options.UseSqlServer in the web app - then the factory override does take hold. From what I can tell, execution never reaches the options builder of the test factory, so no combination of service caching and UseInternalProvider work.

Further technical details

EF Core version: 3.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer and InMemory
Target framework: .NET Core 3.0
Operating system: Win10-x64
IDE: VS2019

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templates

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions