我想测试使用Entity Framework构建的实体。 我担心的是使用实体框架意味着直接使用数据源。 那么任何想法如何单元测试基于Entity Framework的组件?
答案 0 :(得分:51)
对于实体框架4,这看起来很有希望:Testability and Entity Framework 4.0
答案 1 :(得分:7)
显然这很难。 Erik在这里雄辩地提出 - TDD and ADO.NET Entity Framework
答案 2 :(得分:6)
一种廉价的方法是设置一个与真实数据库结构相同的数据库文件,并在单元测试配置中设置连接字符串以指向它。数据库不需要拥有真实数据库的所有表;只是单元测试需要的。
缺点是您需要管理数据库的状态,以便单元测试在运行期间和运行之间不会相互影响。
我知道这种方法在真实和单元测试数据库都使用SQL Express时都有效,但我不知道在SqlExpress数据库中存根用于完整的SQL数据库。
我意识到这是技术上的集成测试,但它可能比重构代码或学习模拟框架更便宜。
示例真实连接字符串:
<add name="DrinksEntities"
connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
;provider connection string="Data Source=localhost\sqlexpress;Initial Catalog=Drinks2;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework""
providerName="System.Data.EntityClient" />
测试连接字符串的单元示例:
<add name="DrinksEntities"
connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient
;provider connection string="Data Source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Inventory.mdf;Integrated Security=True;user instance=True;MultipleActiveResultSets=True;Application Name=EntityFramework""
providerName="System.Data.EntityClient" />
答案 3 :(得分:4)
您将要使用Mocking Framework来检索模拟值,而不是访问实际数据。以下是一些模拟框架的列表以及一些屏幕录像的链接,以帮助您入门:
以下是一些如何入门的截屏视频:
答案 4 :(得分:4)
我想与大家分享另一个输入。我也能够使用TypeMock Isolator测试基于Entity Framework的组件和应用程序。但它是商业性的。
看看这篇文章: Introducing Entity Framework Unit Testing with TypeMock Isolator
答案 5 :(得分:4)
由于实体框架的第1版违反了一些主要的软件设计原则,因此在您的应用程序中使用TDD时,实际上没有任何方法可以应用TDD。如果你正在寻找一个直接的解决方案,我的研究指向NHibernate。它的设计考虑了单元测试。
但是,如果您可以等待,实体框架的下一个版本似乎有希望: Test-Driven Development Walkthrough with the Entity Framework 4.0
答案 6 :(得分:3)
尽管这些例子可能非常简单,但我试图讨论这个问题的可能解决方案。它涉及分离关注点和亲爱的朋友Dependency Injection。
如果您想了解更多详情,请与我联系。
答案 7 :(得分:2)
我同意,一个嘲弄的框架就是你所追求的。您创建未从数据源检索的“模拟”对象,并测试该对象中的数据。我个人一直在与Moq合作,我喜欢它 - 还有Rhinomocks,还有其他人。
答案 8 :(得分:2)
在经历了很多挫折之后,我终于找到了一个解决方案,我至少可以解决部分问题。
首先使用类似于:
的存储库界面public interface IRepository
{
IQueryable<T> GetObjectSet<T>();
}
我们可以用来返回内存集合或真正的DB支持集合。接下来将查询封装到查询对象中,其界面看起来像这样。
public interface IQuery<T>
{
IQueryable<T> DoQuery(IQueryable<T> collection);
}
现在将您的单元测试分为两组。第一组将测试您的查询是否有效。这样做:
[TestMethod]
public void TestQueryFoo()
{
using(var repo = new SqlRepository("bogus connection string"))
{
var query = new FooQuery(); // implements IQuery<Foo>
var result = query.DoQuery(repo.GetObjectSet<Foo>()); // as long as we don't enumerate the IQueryable EF won't notice that the connection string is bogus
var sqlString = ((System.Data.Objects.ObjectQuery)query).ToTraceString(); // This will throw if the query can't be compiled to SQL
}
}
然后,第二组单元测试可以自由地测试您的业务逻辑,而不必担心SQL编译步骤,到目前为止,这是我们遇到最大麻烦的地方。
任何想象力都不完美,触发器显然不会被运行,数据库实现的约束可能会被违反,并且上下文和数据库失去同步的一些问题可能会突然出现。因此,虽然仍然需要端到端集成测试,但有可能捕获IMO在运行时在简单单元测试中出现的最常见问题。
答案 9 :(得分:0)
WPF Application Framework (WAF) 项目的 BookLibrary 示例应用程序展示了如何对基于实体框架的应用程序进行单元测试。
答案 10 :(得分:0)
这是工作模式单元+内存数据库+ t4代码生成的聚合,以自动生成假的EF dbContext。
http://mockingcompetence.wordpress.com/2013/05/20/fakingefdatacontext/
有一些问题(无效的linq到EF查询,没有FK强制执行),此时正好复制了一个真正的EF数据库连接。
然而,拥有内存上下文来快速运行单元测试对于能够进行TDD或任何其他类型的单元测试中心方法几乎是必不可少的。
我将发布上述链接的更新,因为我发现了更多问题。
答案 11 :(得分:0)
您可以使用内存数据库来测试您的Entity Framework模型。 查看here了解更多详情
答案 12 :(得分:-1)
如何使用模拟框架? 在我看来,模拟框架可以帮助您从数据库中隔离您的业务逻辑。