我想测试使用实体框架构建的实体。我担心的是使用实体框架意味着直接使用数据源。那么任何想法如何对基于实体框架的组件进行单元测试?
13 回答
For Enity Framework 4, this looks promising: Testability and Entity Framework 4.0
显然这是非常困难的。Erik 在这里雄辩地提出 - TDD 和 ADO.NET 实体框架
A cheap approach is to set up a database file with the same structure as your real database and set the connection string in your unit test config to point to that. The database doesn't need to have all of the tables that the real one has; just the ones the unit test needs.
A disadvantage is that you need to manage the state of the database so that unit tests don't impact each other or themselves during and between runs.
I know this approach works when both the real and unit testing DBs use SQL Express but I don't know about stubbing in a SqlExpress DB for a full SQL DB.
I realize this is technically integration testing, but it could be cheaper than refactoring your code or learning a mocking framework.
Example real connection string:
<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" />
Example unit testing connection string:
<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" />
我想分享另一个意见。我还能够使用 TypeMock Isolator 测试基于实体框架的组件和应用程序。然而它是商业的。
看看这篇文章: 使用 TypeMock Isolator 介绍实体框架单元测试
Due to the fact that version 1 of the Entity Framework breaks a few major software design principles, there really isn't any way to apply TDD when using it in your application. My research points to NHibernate if you're looking for an immediate solution. It was designed with unit testing in mind.
However, if you can wait, there appears to be hope for the next release of the Entity Framework: Test-Driven Development Walkthrough with the Entity Framework 4.0
我同意,一个模拟框架就是你所追求的。您创建未从数据源检索的“模拟”对象,并测试该对象中的数据。我个人一直在与 Moq 合作,我喜欢它——还有 Rhinomocks,还有其他。
After lots of frustration with this I finally have a solution that I'm happy with for at least part of the problem.
First use a repository interface something like:
public interface IRepository
{
IQueryable<T> GetObjectSet<T>();
}
which we can use to return either an in memory collection or a real DB backed collection. Next encapsulate your queries into a query object with an interface that look something like this.
public interface IQuery<T>
{
IQueryable<T> DoQuery(IQueryable<T> collection);
}
Now divide your unit tests into 2 groups. The first group will test that your queries are valid. do this like so:
[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
}
}
The second set of unit tests can then freely test your business logic without worrying about the SQL compilation step which is, by far, where we run into the most trouble.
Its not perfect by any stretch of the imagination, triggers are obviously not going to be run, DB implemented constraints can be violated, and some issues with the context and database getting out of sync can crop up. So while end to end integration tests are still needed it is possible to catch what is IMO the most common issue to crop up at runtime in simple unit tests.
The BookLibrary sample application of the WPF Application Framework (WAF) project shows how an Entity Framework based application can be unit tested.
Here's an aggregation of the unit of work pattern+ in-memory database + t4 code generation to automatically generate a fake EF dbContext.
http://mockingcompetence.wordpress.com/2013/05/20/fakingefdatacontext/
there are some issues(invalid linq to EF queries and no FK enforcement) with exactly replicating a real EF db connection at this time.
However, having an in-memory context to quickly run unit tests is almost essential to being able to do TDD or any other kind of unit testing centric approach.
I will be posting updates to the above link as I figure out more of the issues.
You could use in-memory data base for testing your Entity Framework model. Look here for more details
使用模拟框架怎么样?在我看来,模拟框架可以帮助您将业务逻辑与数据库隔离开来。