首页 > 解决方案 > 如何使用 InMemory 测试 Entity Framework Core 数据库,并为大量行提供插入功能

问题描述

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

我们之前使用过一个小型 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/将可用选项总结得很好,但我仍然不知道在我们的案例中解决方案会是什么样子,因为我们需要

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

标签: c#asp.net-coretestingentity-framework-corein-memory-database

解决方案


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

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

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

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

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

还需要考虑的事情:您可能还需要在数据库更改(迁移)时更新映像,但您也可以通过始终从最新版本的架构创建映像或在迁移MigrateAsync期间应用迁移来做到这一点图像生成的 CI 过程。这在很大程度上取决于您的数据库更改的频率。

我为 Postgres 数据库做了类似的事情,这些链接帮助我入门。SQL Server 也应该非常相似:

Docker 技巧 #79:在 Docker 映像中保存 Postgres 数据库

构建包含数据的 Docker 映像 Postgres


推荐阅读