如何将 Entity Framework 核心数据库测试为 InMemory,具有大量行的插入功能

How to test an Entity Framework Core database as InMemory with insert functionality for a large number of rows

在我们的一个项目中,我们有一个包含大量表和数千行的数据库。对于我们的集成测试,我们希望我们的测试针对固定的数据库状态 运行,例如 5000 行,以便测试是确定性的并且总是 return 相同的结果。

我们之前使用过小型 Entity Framework Core InMemoryDatabases,我们在其中添加了大约 20 行,如下所示:

private DbContextOptions<OurDataContext> GetInMemoryDbContextOptions()
{
    var options = new DbContextOptionsBuilder<OurDataContext>()
        .UseInMemoryDatabase(databaseName: "foo")
        .Options;

    using (var context = new OurDataContext(options))
    {
        context.OurTable.Add(new OurTable(){...});
        // ...
        context.SaveChanges();
    }
    return options;
}

但是,在我们的新案例中,对于应该从生产数据库派生的这么多行来说,这是不可行的。我们需要一种将真实数据同步到内存数据库中的好方法。如何做到这一点?

理想情况下,我们会使用 SQL Management Studio 将生产数据库的相关部分导出到 SQL 脚本中,并在 Git 中跟踪此 SQL 导出作为一部分我们的测试代码。据我们所见,没有 从 SQL 脚本 导入数据,因为我们无法 运行 SQL 脚本它。

https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/ 很好地总结了可用选项,但我仍然不知道在我们的案例中解决方案会是什么样子,因为我们需要

我们应该选择哪种内存数据库方法?

按照 OP 的要求将我的评论移至答案:

根据您发布的有关测试的 EF Core link (https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing),很明显使用内存中(甚至 SQL Lite)不是 "recommended"仅仅是因为您正在测试不能反映您的生产场景的东西。有人可能会争辩说你不应该测试数据库的实现,但实际上大多数时候它是必要的。例如,我想测试我创建的视图是否返回预期结果或正确生成报告,所以我认为像 OP 要求的那样使用完整的 SQL 服务器是一个有效的点。另一点是,使用 SQL Lite 之类的东西并不能很好地支持您可以使用 EF 进行的所有迁移。例如,我在创建索引时已经 运行 遇到问题。

继续:您可以尝试解决此问题的一种方法是使用 Docker 容器。您可以 运行 SQL 服务器在 Linux 容器 Run SQL Server container images with Docker 中。这个想法是,您可以基于 SQL 服务器创建一个自定义图像,并在您放置 5000 行(或您想要的任何数据)的图像中,构建并推送现成的图像到 docker 注册表。

然后在系统的 CI 期间,您要使用预期数据 运行 进行测试,为您创建的图像启动 docker 容器并连接测试到那个 SQL 服务器实例(只需要将端口映射到主机,通常是 1433)。这样你就可以保证运行你的测试总是从同一组数据开始。

根据构建图像本身,您可以通过多种方式进行操作。您可以使用 CI 本身来创建图像。它可以从某个地方获取数据,或者让一个小程序为您生成数据并将其放入容器中。它可以是一个 .bak 文件或一个 SQL 脚本,其中包含由您的程序生成的一堆插入。然后当你想要你的图像包含 "new" 数据时,你需要做的就是 运行 CI 构建。您可以将标签添加到 Docker 图像,以确保您可以 运行 测试旧版本和新版本的数据,这很酷。

还有一点需要考虑:您可能还需要在数据库更改(迁移)时更新图像,但您也可以通过始终从最新版本的模式创建图像或应用在图像生成的 CI 过程中使用 MigrateAsync 的迁移。当然,这在很大程度上取决于您的数据库更改频率。

我为 Postgres 数据库做了类似的事情,这些 links 帮助我开始了。 SQL 服务器也应该非常相似:

Docker Tip #79: Saving a Postgres Database in a Docker Image

Build Docker Image Postgres With Data Included