Asp.net web api 如何对EF核心迁移执行集成测试

Asp.net web api 如何对EF核心迁移执行集成测试,asp.net-web-api,integration-testing,entity-framework-migrations,ef-core-2.0,Asp.net Web Api,Integration Testing,Entity Framework Migrations,Ef Core 2.0,我已经在这个主题上进行了广泛的搜索,但对于我想做的事情却没有找到任何结果 从高层次上讲,这就是我想要做的: 安排:在测试方法中,调用适当的服务来为数据库种子 操作:运行迁移以更新数据库架构 断言:数据完整性,即种子数据可以根据更新的实体结构进行访问 这有什么意义? 这在上面的断言中有很多描述;数据完整性。此项目中的迁移在应用程序启动时使用Database.Migrate()运行。我希望确保现有数据不会丢失/损坏 我遇到的所有集成测试示例都将运行Database.Migrate()作为测试设置

我已经在这个主题上进行了广泛的搜索,但对于我想做的事情却没有找到任何结果

从高层次上讲,这就是我想要做的:

  • 安排:在测试方法中,调用适当的服务来为数据库种子
  • 操作:运行迁移以更新数据库架构
  • 断言:数据完整性,即种子数据可以根据更新的实体结构进行访问
这有什么意义?
这在上面的断言中有很多描述;数据完整性。此项目中的迁移在应用程序启动时使用
Database.Migrate()
运行。我希望确保现有数据不会丢失/损坏

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

问题:


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

请查看我的其他答案,因为它比下面的方法更新且简单得多。

我能想到的一个选项如下所示……
(请注意,我还没有测试过这一点,这只是目前阶段的理论,所以请随意评论我可能出了什么问题。最后我自己做了笔记,解决了我所看到的问题;笔记对应于标有*或^的项目)

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

在继续使用测试方法之前,您必须在应用迁移Mn+1之前准确地捕获被测系统(SUT)的状态。因此,应采取以下措施:

  • 为迁移创建一个新的测试项目(如果还不存在)
  • 从迁移测试项目中删除所有现有内容^(内容在以下步骤中描述)
  • 将模型中与Mn对应的所有实体的副本放入迁移测试项目中,这些实体需要修改才能生成Mn+1。在合并FISTANDLASTNAME之前,编辑其名称,使其后缀(例如)为
    。因此,由于需要更新实体
    User
    ,请将其副本放在测试项目中,并在\u mergefirstnames和lastnames
    之前将其命名为
    User\u
  • 对需要更新以生成Mn+1的任何上下文*执行相同操作。因此,假设(比方说)需要更新
    MembershipContext
    ,在测试项目中复制它并在\u mergefirstnames和lastnames
    之前调用它
    MembershipContext
  • 最后,对您需要调用的任何服务执行相同的操作,以便为测试数据库设定种子(如果您使用存储库模式,则通常会调用存储库实现来修改数据库,对实体的更改可能会触发对存储库实现的更改)
    现在,对于您的测试方法^^^,您将:

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

    注:
    *:如果将上下文复制到测试项目,则需要手动编辑其中与更新实体对应的任何
    DbSet
    属性,以使用复制的实体。例如,在上面的示例中,如果
    MembershipContext\u\u MergeFirstAndLastNames
    之前有一个属性
    DbSet User{get;set;}
    ,则必须将其更改为
    DbSet User{get;set;}


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

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

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

    上述技术在CI设置中可以很好地工作,在此设置中,以前的所有迁移在合并到生产中之前都已经过测试。在这样的设置中,只有对测试最新的迁移感兴趣才有意义。

    ^^:对于测试
    Up
    迁移效果的每个测试方法,需要使用反向测试方法测试