![](/img/trans.png)
[英]Entity Framework Code First With Exisitng Data - How To Setup Enums?
[英]How to automate DB setup of Entity Framework's Code First in TestContainers for testing?
为了设置TestContainer的MsSqlTestcontainer
进行测试,我复制了dotnet ef migrations script
发出的脚本并将其植入单元测试的设置中(实际代码没有:
void PrepareDb(MsSqlTestcontainer dbTestContainer){
dbTestContainer.ExecScriptAsync(@"CREATE TABLE [DbName] ( /* ... */ )");
}
有没有办法使其自动化,例如,如果数据库模型发生变化,并将MyDbContext
直接连接到TestContainer
的逻辑?
我正在考虑将MyDbContext
代码传递到容器中并在其中运行dotnet ef migrations script
,但我不确定它值得付出多少努力(而且我需要使用已经安装了dotnet
的容器,这是另一个复杂问题..).
这是dbTestContainer
设置,FWIW:
var dbTestContainer = new TestcontainersBuilder<MsSqlTestcontainer>()
.WithDatabase(new MsSqlTestcontainerConfiguration { Password = "whatever secret" })
.WithImage("mcr.microsoft.com/azure-sql-edge")
.WithWaitStrategy(Wait.ForUnixContainer())
.Build()
在测试开始之前连接到容器化数据库并以编程方式运行迁移
dbContext.Database.Migrate();
我遇到了同样的问题,但我设法解决了它,至少是为了满足我自己的基本需求。 如果您仍然需要解决方案,这就是我所做的。
注意:如果有人知道更好的方法或发现以下任何缺陷,我将非常高兴听到。
我有一个IntegrationTestWebApplicationFactory
,我用它来为我的集成测试做通常的配置。 正如 Pavel 已经指出的那样,您可以在测试开始之前以编程方式运行迁移。 为此,我的IntegrationTestWebApplicationFactory
实现了我用于测试的XUnit
的IAsyncLifetime
接口。 此接口要求您实现InitializeAsync
和DisposeAsync
方法。 在InitializeAsync
内部,我运行await dbContext.Database.MigrateAsync();
命令。
这是我的IntegrationTestWebApplicationFactory
类的完整代码:
public class IntegrationTestWebApplicationFactory : WebApplicationFactory<Program>, IAsyncLifetime
{
private readonly TestcontainerDatabase _container;
public IntegrationTestFactory()
{
_container = new TestcontainersBuilder<MsSqlTestcontainer>()
.WithDatabase(new MsSqlTestcontainerConfiguration
{
Username = "sa",
Database = "WeatherApp",
Password = "2@LaiNw)PDvs^t>L!Ybt]6H^%h3U>M",
})
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
.WithCleanUp(true)
.Build();
}
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureTestServices(services =>
{
services.AddDbContext<DemoDbContext>(options => { options.UseSqlServer(_container.ConnectionString); });
});
}
public async Task InitializeAsync()
{
await _container.StartAsync();
using var scope = Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<DemoDbContext>();
await dbContext.Database.MigrateAsync();
}
public new async Task DisposeAsync() => await _container.DisposeAsync();
}
这就是我在集成测试中使用它的方式:
[Theory]
[InlineAutoData]
public async Task GettingWeatherForecastReturnsOkay(WeatherForecast expectedForecast)
{
var client = _integrationTestFactory.CreateClient();
// insert into db what you want to assert
await client.PostAsJsonAsync("WeatherForecast", expectedForecast);
// read from db
var forecasts = await client.GetFromJsonAsync<List<WeatherForecast>>("WeatherForecast");
// do asserts or whatever..
forecasts.Should().NotBeEmpty();
forecasts.Should().ContainEquivalentOf(expectedForecast);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.