我的情况是:
DbContext
次呼叫均来自控制器层DbContext
包含在using语句中并根据内存管理目的进行实例化而不是连接池目的DbContext
注入控制器。我可以改变的条件:
所以,我的问题是:我如何将DbContext
传递给构造函数,以便我可以模拟返回的响应,但保持using语句的可靠性,因为它们往往相互矛盾。
如果我需要停止使用using
语句,我可以,只要有办法确保每次执行请求的操作时都会处理上下文。
对此有什么想法吗?
答案 0 :(得分:0)
这些限制很困难但并非不可能。你没有提到Core会让这件事变得轻而易举。
最有可能的是,创建一个接受DbContext对象的构造函数。在你的单元测试中,创建你的"模拟" DbContext并将其传递给控制器。如果收到DbContext,Controller不会创建DbContext。
另外,在任何测试之前,请考虑创建内存中的EF DbContext用于测试目的,并在测试完成时将其销毁。
在没有IOC的情况下,DI在开发TDD时是惊人的。它内置于.Net Core,因此这些约束是一个死胡同。
答案 1 :(得分:0)
在您要测试的方法中构建DbContext与在代码中实例化依赖项的任何其他具体实例没有什么不同,这意味着您无法使用模拟依赖项进行测试。因此,想到的直接选项是(没有代码/结构更改):
模拟DbContext很麻烦,但可行。一旦你有一个模拟器,我会建议在项目中添加一个像Autofac这样的IoC容器。我不知道会阻止你引入IoC容器的情况,但是如果团队担心它是一个全有或全无的因素而且工作量太大,那么我会向他们保证它是可以添加对项目的最小更改,并且不会破坏现有代码。除了DbContext之外,如果代码没有使用DI / IoC Container,您打算如何处理其他具体依赖?您不必一次性切换所有依赖项/控制器,而是逐步改进它们。
设置容器以解析MVC控制器后,具有默认构造函数的现有控制器不会受到影响。然后,您可以使用容器注册DbContext,并调整受测试的控制器以接受构造函数中的上下文。例如,IoC容器会将DbContext生存期范围设置为每个请求的实例,因此您不需要using {}
块。从那里你的测试可以提供模拟的DbContext,而容器管理上下文的生命周期。
关于使用IoC容器制作单元测试友好的控制器/代码,我最近发布了一篇关于使用Lazy依赖项/ w Autofac的文章,以便为具有多个依赖项的类编写测试。您可以在https://medium.com/@StevePy/writing-easily-testable-code-with-autofac-lazy-properties-f9c63457c8ce
阅读