使用实体框架进行单元测试

时间:2008-11-28 19:01:08

标签: linq unit-testing entity-framework

我想测试使用Entity Framework构建的实体。 我担心的是使用实体框架意味着直接使用数据源。 那么任何想法如何单元测试基于Entity Framework的组件?

13 个答案:

答案 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=&quot;Data Source=localhost\sqlexpress;Initial Catalog=Drinks2;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     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=&quot;Data Source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Inventory.mdf;Integrated Security=True;user instance=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     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。

http://devblog.petrellyn.com/

如果您想了解更多详情,请与我联系。

答案 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)

如何使用模拟框架? 在我看来,模拟框架可以帮助您从数据库中隔离您的业务逻辑。