使用带有 InMemoryDatabase 的 TestStartup 引导 TestServer 失败(.Net 核心)

Bootstrapping TestServer with TestStartup with InMemoryDatabase fails (.Net core)

也许我错过了什么,或者什么东西坏了。我希望知道这里发生了什么。

TLDR:使用 InMemory 数据库引导 TestServer class,得到 (No service for type 'Microsoft.Data.Entity.Storage.IRelationalConnection' has been registered)。有什么线索吗?更多详情如下:

我有一个测试 class,它使用 TestFixture 来 bootstrap:

public AccountControllerTest(TestServerFixture testServerFixture) : base(testServerFixture)
    {
    }

testServerFixture 如下所示: public class TestServerFixture:IDisposable { public TestServer 服务器 { 得到; }

    public HttpClient client { get; }

    public TestServerFixture()
    {
        // Arrange
        var builder = TestServer.CreateBuilder()
            .UseEnvironment("Development")
            .UseStartup<TestPortalStartup>()
            .UseServices(services =>
            {
                // Change the application environment to the mvc project
                var env = new TestApplicationEnvironment();
                env.ApplicationBasePath =
                    Path.GetFullPath(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "..", "MY_APP"));
                env.ApplicationName = "MY_APP";
                //SUPER IMPORTANT: Should be the real application name, else you'll get Roslyn Compiler Errors in your views

                services.AddInstance<IApplicationEnvironment>(env);
            });

        server = new TestServer(builder);

        client = server.CreateClient();
    }

    public void Dispose()
    {
        server.Dispose();
        client.Dispose();
    }
}

如您所见,它使用了一个 TestPortalStartup,如下所示: public class TestPortalStartup:启动 { 私人模拟账户RegistrationClientMock;

    public TestPortalStartup(IHostingEnvironment env, IApplicationEnvironment appEnv) : base(env, appEnv)
    {
    }

    public override void SetUpDataBaseAndMigrations(IServiceCollection services)
    {
        services
          .AddEntityFramework()
          .AddInMemoryDatabase()
          .AddDbContext<CmsDbContext> (
            options => options.UseInMemoryDatabase()
        );
    }


    public override void AddFrameworkDependencies(IServiceCollection services)
    {
    // ... not relevant
    }

}

正如您在 SetUpDataBaseAndMigrations 中看到的,我们 bootstrap 一个 InMemoryDatabase 和一个 DbContext.

我以前使用过这个结构来测试处理数据库的服务。 (但这是孤立的)。

现在通过集成测试我最终未能通过 bootstrap 测试:

Result StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.Data.Entity.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor) at Microsoft.Data.Entity.RelationalDatabaseFacadeExtensions.GetRelationalConnection(DatabaseFacade databaseFacade) at Microsoft.Data.Entity.RelationalDatabaseFacadeExtensions.GetDbConnection(DatabaseFacade databaseFacade) at MY_APP.Portal.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in MY_APP/Startup.cs:line 175 Result Message: One or more errors occurred. No service for type 'Microsoft.Data.Entity.Storage.IRelationalConnection' has been registered. The following constructor parameters did not have matching fixture data: TestServerFixture testServerFixture

如果您想知道 MY_APP/Startup.cs(第 175 行)发生了什么,那就是:

 logger.LogInformation($"Using SQL Connection: {dbContext.Database.GetDbConnection().DataSource}");

运行 'normal' 数据库(即不是内存中的数据库)将通过测试。

所以看起来有些 dependencies/wiring 不见了?有人有这方面的经验吗?线索?等等

在我 post 在 AspDotNet github 上回答这个问题后,答案是来自 EntityFramework 的 InMemoryDatabase 本身并不打算像这样进行集成测试。

另一种方法是使用 SQLite - 但也可以在内存模式下使用。

自从创建所有这些(从零开始到完全工作的集成测试)以来,我花了很长时间才弄明白。我想我会在博客中总结这一切 post:

http://www.stefanhendriks.com/2016/04/29/integration-testing-your-dot-net-core-app-with-an-in-memory-database/