【问题标题】:How to perform integration testing on EF Core migrations如何对 EF Core 迁移执行集成测试
【发布时间】:2019-03-10 09:51:10
【问题描述】:

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

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

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

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

我遇到的所有集成测试示例几乎都运行 Database.Migrate() 作为测试设置的一部分,然后是种子,然后是断言。然而,这仅在测试给定 latest 模式的数据访问层时有用(所有迁移都已应用)。它在测试特定迁移对已存在数据的影响时没有用处。

问题:

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

【问题讨论】:

    标签: asp.net-web-api integration-testing entity-framework-migrations ef-core-2.0


    【解决方案1】:

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

    我能想到的一个选项将按如下方式工作...
    (请注意,我没有对此进行测试,这只是现阶段的理论,所以请随时评论我可能出错的地方。我自己在最后做了笔记,解决了我看到的问题;笔记对应于项目标有 * 或 ^)

    假设您已经有迁移IM、M1、M2、...、Mn,其中IM是初始迁移,迁移Mn 是最后一次成功测试的迁移。现在假设您要测试一个新的迁移Mn+1,这是(除其他外)更新User 实体以不再具有单独的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. 最后,对您需要调用的任何服务执行相同的操作以播种测试数据库(如果您使用存储库模式,通常会调用存储库实现来修改数据库和对您的实体的更改可能会触发对您的存储库实现的更改)。


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

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


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

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

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

    ^:迁移测试项目需要在测试新迁移时清除所有内容。
    非正式证明:假设这不是必需的。使用上面的示例,该项目将包含一个引用对应于迁移Mn+1User 实体的测试方法。现在假设对User 进行了更新,这会导致更新的迁移Mn+2。如果现有的测试方法以不再适用的方式引用User,则它可能不再编译。 ∎

    上述技术在 CI 设置中运行良好,其中所有先前的迁移在合并到生产之前都已经过测试。在这样的设置中,只对测试最新迁移感兴趣是有意义的。

    ^^:对于每个测试Up迁移效果的测试方法,都需要一个逆向测试方法来测试相应Down迁移的效果。

    【讨论】:

    • 我希望有比这更简单的方法,这就是为什么我不接受这个作为答案。
    【解决方案2】:

    这是一种比我描述的其他方法简单得多的方法。

    安排:使用IMigrator.Migrate 将所有迁移应用到(包括)需要测试的迁移之前的迁移。 那么关键是:使用SqlCommand 直接为数据库做种。

    Act:应用需要测试的迁移。

    断言。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-07
      • 2012-08-11
      • 2018-10-02
      • 1970-01-01
      • 2021-11-23
      • 2017-05-30
      • 2021-07-15
      相关资源
      最近更新 更多