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

时间:2020-06-09 08:44:33

标签: c# asp.net-core testing entity-framework-core in-memory-database

在我们的一个项目中,我们有一个包含大量表和数千行的数据库。对于我们的集成测试,我们希望我们的测试能够在固定的数据库状态(例如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/总结了所有可用选项,但我仍然不知道解决方案在我们的情况下会是什么样子,因为我们需要

  • 能够将生产数据库中的数据匿名化为可以存储在Git中的状态。如果需要,则应完成此同步,因此明确地不是每次我们要运行测试时。我们无法手动为数千行编写插入内容。
  • 一种将数据库重置为每次测试运行之前保存的存储的方法。

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

1 个答案:

答案 0 :(得分:1)

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

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

继续前进:您可以尝试解决此问题的一种方法是使用Docker容器。您可以在Linux容器Run SQL Server container images with Docker中运行SQL Server。这个想法是,您可以基于SQL Server创建一个自定义映像,并在该映像中放入5000行(或所需的任何数据),构建并将可用映像推入Docker注册表。

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

根据构建图像本身的方法,您可以采用多种方法。您可以使用CI本身来创建映像。它可以从某处获取数据,或者有一个小程序为您生成数据并将其放入容器中。它可以是.bak文件或带有程序生成的一堆插入内容的SQL脚本。然后,当您想让图像包含“新”数据时,您所需要做的就是运行CI构建。您可以在Docker映像中添加标签,以确保您也可以针对新旧数据运行测试。

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

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

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

Build Docker Image Postgres With Data Included