使用带有 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:
也许我错过了什么,或者什么东西坏了。我希望知道这里发生了什么。
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: