entity-framework - 如何使 DbContext 在 using 语句中与单元测试一起使用?
问题描述
我的情况是这样的:
- 我正在开发一个没有实现存储库模式的 ASP.NET MVC 项目
- 所有
DbContext
调用都是从控制器层进行的 DbContext
包装在 using 语句中,并在必要时出于内存管理目的而不是连接池目的进行实例化- 我们需要对这些控制器进行单元测试,这意味着将 注入
DbContext
控制器。 - 我们没有使用 IoC 容器。我必须在无参数构造函数中创建一个新实例,并在调用控制器操作的整个生命周期中使用它。
- 我无法改变这些条件中的大部分。
我可以改变的条件:
- 摆脱 using 语句,如果一个可靠的选项可以取代它。
- 承认此代码无法按原样测试,然后继续在其他地方花费精力。
所以,我的问题是:如何将 a 传递DbContext
给构造函数,以便模拟返回的响应,但保持 using 语句的可靠性,因为它们往往相互矛盾。
如果我需要停止使用该using
语句,我可以,只要有一种方法可以确保每次执行请求的操作时都会释放上下文。
对这个有什么想法吗?
解决方案
在您要测试的方法中构造 DbContext 与在代码中实例化依赖项的任何其他具体实例没有什么不同,这意味着您无法使用模拟依赖项进行测试。所以想到的直接选项是(没有代码/结构更改):
- 实现一个内存数据提供程序以将 EF 指向以进行单元测试。
- 设置可以在测试运行之间恢复的已知状态数据库。(更多的是集成测试,不太适合 TDD,您希望测试可以非常快速、非常频繁地运行。)
- 由于缺少 DI/IoC,将其放入“不是为单元测试而设计”的桶中
模拟 DbContext 很麻烦,但是可行。一旦你有了一个可以模拟的东西,我建议你在项目中添加一个像 Autofac 这样的 IoC 容器。我不知道会阻止您引入 IoC 容器的情况,但如果团队担心它是一个全有或全无的重构和太大的工作,那么我会向他们保证它可以在对项目进行最小更改的情况下添加,并且不会破坏现有代码。除了 DbContext,如果代码没有使用 DI/IoC Container,你打算如何处理其他具体的依赖关系?您不必一次性切换所有依赖项/控制器,而是逐步改进它们。
一旦容器被设置为解析 MVC 控制器,具有默认构造函数的现有控制器将不会受到影响。然后,您可以在容器中注册您的 DbContext,并调整您的被测控制器以接受构造函数中的上下文。例如,IoC 容器会将 DbContext 生命周期范围设置为 Instance per Request,因此您不需要该using {}
块。从那里你的测试可以提供模拟的 DbContext,而容器管理上下文的生命周期。
关于使用 IoC 容器制作单元测试友好的控制器/代码,我最近发布了一篇关于使用 Lazy dependencies /w Autofac 来为具有多个依赖项的类编写测试的文章。您可以在https://medium.com/@StevePy/writing-easily-testable-code-with-autofac-lazy-properties-f9c63457c8ce阅读
推荐阅读
- c# - SQL 如何替换一个值
- python - 使用 python 和请求,如何进行正确的 POST 调用以及在哪里找到标头?
- android - FirebaseAppDistribution:appDistributionUpload gradle 命令中缺少应用程序 ID
- mysql - 跨列和行计算值的实例
- javascript - 使用 redux 钩子时使用 redux 操作的最佳选择是什么?
- sql - Impala 2.11:AnalysisException:选择列表中不支持子查询
- swift - 在 SwiftUI 中获取当前的经纬度
- c++ - 是否可以禁止一个类被动态转换为?
- git - Git - 将发布分支合并到主分支
- tensorflow - 任何想法如何解决激活函数的问题?