猿问
下载APP

单元测试DbContext

单元测试DbContext

我研究了一些关于我可以用来对DbContext进行单元测试的技术的信息。我想在上下文中添加一些内存数据,以便我的测试可以针对它运行。我正在使用Database-First方法。

我发现最有用的两篇文章是这个这个。该方法依赖于创建一个MyContext和FakeContext都将实现的IContext接口,允许模拟上下文。

但是,正如某些人所指出 的 那样,我试图避免使用存储库来抽象EF,因为EF 4.1已经通过DbSet和DbContext实现了存储库和工作单元模式,我真的想保留EF实现的所有功能。团队无需使用通用存储库维护它们,正如我在其他项目中所做的那样(这有点痛苦)。

使用IContext会引导我走同一条路(或者不是吗?)。

我考虑创建一个继承自主MyContext的FakeContext,从而利用它下面的DbContext运行我的测试而不需要访问数据库。我找不到类似的实现,所以我希望有人可以帮助我。

我做错了什么,或者这会导致我遇到一些我没想到的问题?


123456qqq
浏览 54回答 3
3回答

慕的地2183247

问自己一个问题:你打算测试什么?你提到FakeContext并嘲笑上下文 - 为什么同时使用它们?这些只是做同样的不同方式 - 提供仅测试上下文的实现。还有一个更大的问题 - 伪造或模拟上下文或集合只有一个结果:您不再测试您的真实代码了。简单的例子:public&nbsp;interface&nbsp;IContext&nbsp;:&nbsp;IDisposable{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IDbSet<MyEntity>&nbsp;MyEntities&nbsp;{&nbsp;get;&nbsp;}}public&nbsp;class&nbsp;MyEntity{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;Id&nbsp;{&nbsp;get;&nbsp;set;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;string&nbsp;Path&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;}public&nbsp;class&nbsp;MyService{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;bool&nbsp;MyVerySpecialNetMethod(e) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;File.Exists(e.Path); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;IEnumerable<MyEntity>&nbsp;GetMyEntities() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using&nbsp;(IContext&nbsp;context&nbsp;=&nbsp;CreateContext()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;context.MyEntities &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Where(e&nbsp;=>&nbsp;MyVerySpecialNetMethod(e)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Select(e) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ToList(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}现在想象一下,你的SUT中有这个(被测系统 - 在单元测试的情况下,它是一个单位=通常是一个方法)。在测试代码,您提供FakeContext与FakeSet和它的工作-你将有一个绿色的测试。现在在生产代码中,您将提供另一个派生的DbContext,DbSet并且您将在运行时获得异常。为什么?因为通过使用FakeContext你也改变了LINQ提供程序,而不是LINQ to Entities,你正在运行LINQ to Objects,所以调用无法转换为SQL的本地.NET方法以及LINQ to Entities中没有的许多其他LINQ功能!您还可以通过数据修改找到其他问题 - 参照完整性,级联删除等。这就是为什么我认为处理context / LINQ to Entities的代码应该用集成测试覆盖并针对真实数据库执行的原因。

九州编程

我正在开发一个开源库来解决这个问题。http://effort.codeplex.com一个小预告片:您不必添加任何样板代码,只需调用库的相应API,例如:var&nbsp;context&nbsp;=&nbsp;Effort.ObjectContextFactory.CreateTransient<MyContext>();起初这看起来很神奇,但创建的ObjectContext对象将与内存数据库通信,根本不会与原始真实数据库通信。术语“瞬态”是指该数据库的生命周期,它仅存在于创建的ObjectContext对象期间。并发创建的ObjectContext对象与专用数据库实例进行通信,数据不会与它们共享。这样可以轻松编写自动化测试。该库提供了各种功能来自定义创建:跨实例共享数据,设置数据库的初始数据,在不同的数据层上创建假数据库...查看项目站点以获取更多信息。

一只甜甜圈

从EF 4.3开始,您可以在创建上下文之前通过注入假来对代码进行单元测试DefaultConnectionFactory。
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答