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

时间:2019-03-10 09:51:10

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

我对此主题进行了广泛搜索,结果发现零结果完全符合我的意愿。

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

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

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

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

问题:

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

2 个答案:

答案 0 :(得分:3)

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

我能想到的一种方法如下:
(请注意,我还没有对此进行测试,这只是理论上的问题,所以请随时评论我可能出了什么问题。我在最后做笔记的目的是解决我看到的问题;笔记对应于项目标有*或^)

假设您已经有迁移 IM,M1,M2,...,Mn ,其中 IM 是初始迁移,而迁移 Mn 是上次成功测试的迁移。现在,假设您要测试新的迁移 Mn + 1 ,这是(除其他事项外)将User实体更新为不再具有单独的FirstNameLastName个属性,但是只有一个Name个属性。让我们给它命名为MergeFistAndLastNames

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

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


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

  • 安排:使用IMigrator.Migrate应用所有迁移,直到及包括 Mn 。然后调用所需的服务来播种测试数据库**。
  • 行动:再次使用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 + 1 相对应的User实体。现在,假设对User进行了更新,这导致了更新的迁移 Mn + 2 。如果现有测试方法以不再适用的方式引用User,则可能无法再编译。 ∎

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

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

答案 1 :(得分:0)

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

安排:使用IMigrator.Migrate将所有迁移应用到(并包括)之前需要测试的迁移。 然后是密钥:使用SqlCommand直接为数据库添加种子。

操作:应用需要测试的迁移。

声明。