0

我们试图弄清楚下面的代码中单元测试对于基本情况的意义。做这个有益的单元测试吗?我们并不试图测试实体框架。我们只是想确保lambda表达式做它应该做的......我们的想法是,我们将使用DI来传递IQueryable的SOMETHING ..实际上它将是EF,但是对于单元测试并且将是POCO对象/集合。这有道理吗?我们刚刚开始着手并希望在超越此基本代码之前掌握这些概念。如何用lambda表达式进行单元测试实体框架/存储库模式

public class CongressRepository 
{ 
    CongressDb_DevEntities context = new CongressDb_DevEntities(); 

    CongressRepository(DbContext db) 
    { 
     context = (CongressDb_DevEntities) db; 
    } 

    public IQueryable<tMember> GetAllMembers 
    { 
     get { return context.tMembers; } 
    } 

    public IQueryable<tMember> GetVotingMembers 
    { 
     get { return context.tMembers.Where(x => x.age > 18); } 
    } 
} 
+0

Sooo你问我们是否应该单元测试这些方法?这些测试将会很快写出来,如果你不熟悉写测试,就不会习惯它们。我不明白你为什么特别提到lambda/EF,你到底有什么疑问? –

+0

我们知道我们应该..我想这不是很清楚..我们问的是......我的意思是我们可以手动创建自动生成DbContext的东西的对象的集合......并将那些完全可查询的与默认的EF DbContext行为相同的方式? – punkouter

回答

1

对于使用DbContext的对象进行单元测试,您必须将其作为接口注入到存储库对象中。请按照下列步骤:

1,创建一个包含所有的DbContext性质的接口,并从中派生的DbContext:

public interface ICongressDbContext { 
    IDbSet<Member> Members { get; set; } 
    // repeat for all dbsets 
} 

告诉上司这个接口在构造函数中你的资料库。这是你的依赖注入:

private ICongressDbContext context; 
public CongressRepository(ICongressDbContext context){ 
    this.context = context; 
} 

你将要传递的上下文的实例中使用依赖注入框架像Autofac,也可以创建你实例化你的对象实例。

3.创建IDbSet的通用实现:https://gist.github.com/LukeWinikates/1309447。我们称之为FakeDbContext。

4.现在你有一个可模拟的接口和一个通用的DbSet实现,你可以创建你的模拟DbContext和你的模拟IDbSets。使用Moq,如下所示:

 var dataContext = new Mock<ICongressDbContext>(); 
     var members = new List<Member> { // create your test data here }; 
     // set up the mocked context to use your fake db set with test data 
     dataContext.SetupProperty(c => c.Members, new FakeDbContext<Member>(members)); 

     var repository = new CongressRepository(dataContext.Object); 

     // start writing your test methods here 

这将测试使用DbContext而不是DbContext本身的对象。
除了单元测试之外,您还需要编写使用真实DbContext的集成测试。在访问数据库时,IQueryable支持许多不支持的方法。您还需要确保您的数据模型已正确映射到数据库。

我希望这可以帮助您开始。

+0

好的。这似乎是要走的路线..即使line2objects不同于linq2ent ..也许它足够接近 – punkouter

2

的原因之一为单元测试代码确保准确性...

在你的榜样有人在他们的18岁生日或者它的任何和他们19岁生日的日子不能投票。我猜测它应该是:它涵盖了一系列合理的成功和失败值

public IQueryable<tMember> GetVotingMembers 
{ 
    get { return context.tMembers.Where(x => x.age >= 18); } 
} 

单元测试有助于确保您的代码做什么你就意味着:-)


但我们试图找到一个为什么要问的是单元测试 的工作方式。

它可能是一个真正的痛苦! EF6刚刚发布,使它更容易嘲笑DbContext,但现在需要很多设置...

重要的是,Linq-to-Etities和Linq-to-Objects之间存在差异,所以你确实需要单元测试和集成测试。

有很多博客和SO questions相关,虽然...使用FakeDbSet作为一些谷歌福的起点。

+1

你的代码与他的差别如何? –

+0

Doh!漫长的一天: -/ –

+1

是的。我们知道我们应该单元测试。这对于初学者来说是一个很好的例子..但是我们试图找到一个为什么要问的是单元测试的工作原理...... EF与手动EF?我们很难找到一种方法来解释这个...我们正在尝试UNIT测试..而不是INTEGRATION测试 – punkouter

5

EF使用LINQ to Entities,但是当嘲笑EF时你会切换到LINQ to Objects。这可能会导致您的单元测试误报,因为在LINQ to Entities和LINQ to Objects之间存在差异。没有集成测试,您只会在生产环境中看到这些差异/错误。

+0

那么你是说人们通常这样做的方式是模拟执行查询的对象,然后将剩余的代码单元化?在GetAllMembers()的情况下,在MOCK之后没有任何代码留下了......因此,我想我不会单元测试这种方法吗? – punkouter

+0

在TDD中,只有在进行测试之后才能使用该方法。测试将描述GetAllMembers结果应该用于已知数据。这有助于防止未来意想不到的副作用发生变化...... –

相关问题