【问题标题】:How to make a legacy system heavily reliant on Entity Framework more testable?如何使严重依赖实体框架的遗留系统更易于测试?
【发布时间】:2015-10-14 04:34:19
【问题描述】:

我们有一个相当大的系统(约 1m 行),它严重依赖 Entity Framework 6。这意味着我们的 DbContext 可以到处传递和使用。

我们还有很多使用实际 SQL Server 数据库的“单元”测试。每台运行测试的机器都有一个专用的数据库,在运行每个测试之前,该数据库会被擦除并设置所需的数据。

这在速度、可维护性、易用性等方面当然并不理想。

我的最终目标是让我们所有的单元测试(大约 5k 测试)不使用实际的数据库,而是使用某种模拟。我知道这个过程并不容易,但我也希望它尽可能不那么痛苦。

我怎样才能使我的测试更快、更单元化?

【问题讨论】:

  • 指南和想法...请阅读有关适合此处的问题类型的帮助。
  • “~1m 行” - 这不是“相当大”,而是 大量

标签: entity-framework unit-testing


【解决方案1】:

这里只有一个选择,那就是制作一个内存系统。内存中的不幸部分是它不能很好地与实体框架融合,就像根本一样。

建议使用您已经设置好的模拟数据库来完成 Entity Framework 的所有模拟。

所以好消息是您可以自己在内存中完成!坏消息是,您可以在记忆中自己完成。

您将不得不创建实体框架的镜像实现,该实现仅适用于内存中的一组信息。在许多方面,这类似于内存缓存系统中的事件驱动,并且您将从创建用于在内存中模拟的自定义实现中获得的好处是您可以轻松地将其移植到支持缓存数据库信息并允许接口用于查询该信息。

这将公开实时数据的事件驱动推送技术 (SignalR) 等功能。也会花费很多时间。如果实现实体框架的内存模拟所需的开发时间少于由于在模拟数据库中等待测试完成而损失的时间,那么这可能是值得的。

【讨论】:

  • 实现提供程序看起来很复杂,但我想到了类似的东西可能会更容易。我会让 DbContext 实现一个接口,并在整个系统中使用这个接口。在我们的测试中,我将用模拟实例替换 DbContext 的真实实例。听起来可行吗?
【解决方案2】:

我们还有很多使用实际 SQL Server 数据库的“单元”测试。每台运行测试的机器都有一个专用的数据库,在运行每个测试之前,该数据库会被擦除并设置所需的数据。

这在速度、可维护性、易用性等方面当然并不理想。

我的最终目标是让我们所有的单元测试(大约 5k 测试)不使用实际的数据库,而是使用某种模拟。我知道这个过程并不容易,但我也希望它尽可能不那么痛苦。

我不同意你的结论。我建议您保留现有的专用测试数据库,我实际上认为使用实际数据库进行测试是一个好主意,因为它会揭示任何数据层问题,例如如果有人更改了数据库架构而没有反映在您的EF 实体类。 EF 本身经过了很好的测试,因此在我个人看来,对 EF 生成的类进行代码覆盖是一件愚蠢的事情,而实体类和数据库之间的脱节可能是事情可以(并且将会)发展的第一大领域错了。

我了解您对使用这种方法的性能问题,当然还有潜在的优化,例如在运行每个测试之前不重置数据库(也许让测试假设数据库在开始之前处于已知的“良好状态” ) 并且只有在测试套件完成后才重置它。

【讨论】:

  • 我们测试中的性能瓶颈是测试本身对数据库的调用。我希望我们的开发人员在打破测试时能得到快速的反馈,而以目前的速度这是不可能的。每个测试套件重置一次数据库会破坏我们的大部分测试(依赖于干净的数据库),并且需要我们手动修复所有测试。
猜你喜欢
  • 2012-10-05
  • 2010-12-21
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多