如何对 EF Core 迁移执行集成测试

Ash*_*Ash 8 integration-testing asp.net-web-api ef-core-2.0 entity-framework-migrations

我对这个主题进行了广泛的搜索,并发现我想要做的事情的结果为零。

从高层次来看,这就是我想做的:

  • 安排:在测试方法中,调用适当的服务来为数据库播种。
  • 操作:运行迁移以更新数据库架构。
  • 断言:数据完整性,即可以根据更新的实体结构访问种子数据。

这有什么意义呢?
嗯,上面的断言已经描述得差不多了;数据的完整性。此项目中的迁移是在应用程序启动时使用Database.Migrate(). 我想确保现有数据没有丢失/损坏。

我遇到的所有集成测试示例几乎都Database.Migrate()作为测试设置的一部分运行,然后进行播种,然后进行断言。然而,这只适用于测试给定最新架构的数据访问层(已应用所有迁移)。它对于测试特定迁移对已存在数据的影响没有用处。

问题:

其他人如何解决跨迁移测试数据完整性的问题?我正在寻找一种能够与 CI 管道配合良好的设置。

Ash*_*Ash 4

请参阅我的其他答案,因为它比以下方法更新且简单得多。

我能想到的一个选项,工作原理如下...
(请注意,我还没有测试过这一点,这只是现阶段的理论,所以请随意评论我可能出错的地方。我已经做了最后我自己注释了我所看到的问题;注释对应于标有 * 或 ^ 的项目

假设您已经有迁移IM, M1, M2, ..., Mn,其中IM是初始迁移,迁移Mn是最后一次成功测试的迁移。现在,假设您要测试新的迁移Mn+1User ,这是(除其他外)更新实体不再具有单独的FirstNameLastName属性,而是具有单个属性的结果Name。我们给它起个名字吧MergeFistAndLastNames

在继续执行测试方法之前,您必须准确捕获被测系统 (SUT) 在应用迁移Mn+1之前的状态。因此请执行以下操作:

  1. 创建一个新的迁移测试项目(如果尚不存在)。
  2. 从迁移测试项目中删除所有现有内容^(内容在以下步骤中进行描述)。
  3. 将模型中与Mn对应的所有实体的副本放入迁移测试项目中,需要对其进行修改才能生成Mn+1。编辑他们的名字以添加后缀(例如)Before_MergeFistAndLastNames。因此,由于实体User需要更新,请将其副本放置在测试项目中并将其命名为User_Before_MergeFirstAndLastNames.
  4. 对需要更新的任何上下文*执行相同的操作以生成Mn+1。因此,假设(比方说)需要MembershipContext更新,请在测试项目中复制它并调用它MembershipContext_Before_MergeFirstAndLastNames
  5. 最后,对您需要调用的任何服务执行相同的操作,以便为测试数据库提供种子(如果您使用存储库模式,则通常会调用您的存储库实现来修改数据库并更改您的数据库)实体可能会触发您的存储库实现的更改)。


现在对于您的测试方法^^,您将:

  • 安排:使用 来应用所有迁移,直至并包括MnIMigrator.Migrate。然后调用所需的服务来为测试数据库播种**。
  • 做法:IMigrator.Migrate再次使用时,施以迁移Mn+1
  • 断言:数据完整性***。


注意:
*:如果将上下文复制到测试项目,则DbSet其中与更新实体对应的任何属性都需要手动编辑才能使用复制的实体。例如,在上面的示例中,如果MembershipContext_Before_MergeFirstAndLastNames有一个属性DbSet<User> User {get; set;},则必须将其更改为DbSet<User_Before_MergeFirstAndLastNames> User {get; set;}

**:您可能需要调用多个服务。如果您到处使用 IoC,那么注入复制的服务应该相对容易。

***:数据完整性断言实际上取决于您正在测试的特定迁移及其潜在影响。对于上面给出的示例,可能值得检查使用(旧方式)单独的名字和姓氏播种的用户是否仍然可以通过更新来检索,更新UserService应该返回User等于Name名字和姓氏的串联名称。

^:测试新迁移时需要清除迁移测试项目中的所有内容。
非正式证明:我们假设不需要这样做。使用上面的示例,该项目将包含一个测试方法,该方法引用与迁移Mn+1User对应的实体。现在假设对 进行了更新,这导致更新的迁移Mn+2。如果现有的测试方法以不再适用的方式进行引用,则它可能无法再编译。∎ 上述技术在 CI 设置中效果很好,其中所有以前的迁移在合并到生产中之前都已经过测试。在这样的设置中,只对测试最新的迁移感兴趣是有意义的。 ^^:对于每个测试迁移效果的测试方法,都需要一个逆向测试方法来测试相应迁移的效果。UserUser



UpDown