在ASP.NET Core WebApplicationFactory中重写EF Core DbContext

时间:2019-10-14 11:09:11

标签: c# asp.net-core entity-framework-core asp.net-core-3.0 entity-framework-core-3.0

我有一个ASP.NET Core 2.2 WebApi项目,它也使用EF Core 2.2。通过与WebApplicationFactory<T>的集成测试对项目进行了测试。

我试图将Web api项目迁移到netcore / aspnetcore 3,效果很好。我偶然发现的是迁移测试。

我有以下代码可在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...
            });
        }
    }

它使用InMemoryProvider将EF Core DbContext替换为DbContext。

迁移到3.0后,不再替换。我总是收到配置了SQL Server的DBContext。

如果我在应用程序(services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString)))的ConfigureServices中删除了Service.Startup调用,它可以工作,但这不是解决方案。

在注册也不起作用的内存上下文之前,我还尝试过services.RemoveAll(typeof(MyContext))

2 个答案:

答案 0 :(得分:2)

位于https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1的更新文档可能会有所帮助。关键片段更改是删除先前的上下文服务注册:

// 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();

答案 1 :(得分:-1)

确保有一个构造函数以DbContextOptions选项作为参数,并且OnConfigure没有重写:

MyContext.cs

MyContext(DbContextOptions<MyContext> options)
 :base(options)
{}

TestStartup.cs

services.AddDbContext<MyContext>(
        optionsBuilder => {
            optionsBuilder.UseInMemoryDatabase("MyDb");
            });