71

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

4

13 回答 13

50

For Enity Framework 4, this looks promising: Testability and Entity Framework 4.0

于 2010-06-09T09:30:55.227 回答
7

显然这是非常困难的。Erik 在这里雄辩地提出 - TDD 和 ADO.NET 实体框架

于 2008-11-28T22:28:55.730 回答
6

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=&quot;Data Source=localhost\sqlexpress;Initial Catalog=Drinks2;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     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=&quot;Data Source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\Inventory.mdf;Integrated Security=True;user instance=True;MultipleActiveResultSets=True;Application Name=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" />
于 2011-10-22T16:35:57.307 回答
4

您将希望使用模拟框架来检索模拟值,而不是访问真实数据。以下是一些模拟框架的列表和一些截屏视频的链接,可帮助您入门:

以下是一些关于如何开始的截屏视频:

于 2008-12-01T01:56:12.487 回答
4

我想分享另一个意见。我还能够使用 TypeMock Isolator 测试基于实体框架的组件和应用程序。然而它是商业的。

看看这篇文章: 使用 TypeMock Isolator 介绍实体框架单元测试

于 2009-09-14T23:29:04.530 回答
4

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

于 2010-01-26T04:30:41.037 回答
3

尽管这些示例可能非常简单,但我已尝试讨论此问题的可能解决方案。它涉及关注点分离和我们亲爱的朋友依赖注入。

http://devblog.petrelyn.com/

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

于 2009-05-18T20:56:08.307 回答
2

我同意,一个模拟框架就是你所追求的。您创建未从数据源检索的“模拟”对象,并测试该对象中的数据。我个人一直在与 Moq 合作,我喜欢它——还有 Rhinomocks,还有其他。

于 2008-12-01T01:49:27.727 回答
2

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.

于 2013-06-07T18:38:34.177 回答
0

The BookLibrary sample application of the WPF Application Framework (WAF) project shows how an Entity Framework based application can be unit tested.

于 2010-07-28T16:57:13.873 回答
0

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.

于 2013-05-30T10:37:10.450 回答
0

You could use in-memory data base for testing your Entity Framework model. Look here for more details

于 2013-10-15T12:03:05.487 回答
-1

使用模拟框架怎么样?在我看来,模拟框架可以帮助您将业务逻辑与数据库隔离开来。

于 2008-11-29T17:24:49.010 回答