测试Linq查询EF和仓储模式

3
相信我,在SO上我已经看过很多关于这个问题的文章和问题,但是没有找到令人满意的答案。以Matt Robert的教程中的存储库模式和单元测试为例:
我不明白...两个存储库是否包含完全相同的查询逻辑?看起来是这样的,如果是这样的话,那么这是一个有用的模式吗?这意味着每当我在虚拟存储库中更改查询时,我都必须更改实际存储库中的查询逻辑-那听起来很麻烦,也容易出问题。
我希望将查询保留在一个方法中并测试该方法。后来我想到可以像这样做:
//Student can be from the db or a fake list
public person GetStudent(IEnumerable<Student> students,int studentid)
{
   return students.FirstOrDefault(s =>s.PersonId ==studentid);
}

//unit test
    Assert.IsNull(GetStudent(fakeStudentList, -1))
//actual code
    var student =  GetStudent(entities.students,-1) 

是否有一种模式可以模仿上述模式?如果有,那么它是什么?或者实际上就是存储库模式的工作方式?如果是这样,为什么感觉存储库模式会重复代码?

还有,努力方面...看看这个可怕的例子: example :S?


1
好问题,好用户名(迫不及待等待第13本书!)+1 - Brian
1
@Brian 书已经出版了 :P - Lews Therin
1
咦...我是说第14本书,我看到它已经出版了! - Brian
@Brian Yep,不幸的是我正在与设计模式和测试斗争,以开始阅读 :( 但很快 :P - Lews Therin
我本来想说“为你的存储库编写单元测试,然后模拟上下文”。但是我读了这个答案,意识到事情没有那么简单 - http://stackoverflow.com/a/1894066/201648。不过,我认为该回答中的链接可能对你有用。 - Aaron Newton
@AaronNewton 是的,我本来想模拟上下文,但显然那是“危险”的。其他例子都太复杂了。谢谢,我会查看那个链接的。 - Lews Therin
1个回答

2

虽然信息不是很充分,但我认为你的仓储模式存在缺陷。

GetStudent()函数中不应该传入学生集合。 GetStudent应该是一个内部已知学生列表是什么样子,无论是文件、List、数据库等的类的一部分。

因此,您的“虚假”存储库可能具有相同的逻辑,或者它可能只返回硬编码的虚拟Student。如果您正在伪造存储库,则我认为它是因为您正在测试需要存储库的其他内容,因此它不应关心它如何获得Student

此外,您引用的文章只提到了一个存储库,因此我不确定为什么需要复制它。


如果GetStudent()知道Student列表或某些数据结构,我认为这是不好的设计。学生列表来自哪里并不重要 - 我应该能够测试查询一次。至于文章,那是因为不幸的是我找不到同时实现两个存储库的示例。但是实现存储库会产生重复的想法,尽管我仍在继续搜索。 - Lews Therin
1
学生资源库类知道数据库/资源库是一种不好的设计,这样做有什么意义呢?否则,学生资源库类还有什么存在的价值? - Jeff Siver
1
这样想 - 你不是测试假的东西 - 你是创建假的东西来测试其他东西。 - D Stanley
好的,认为存储库不执行任何复杂查询是有道理的吗?它的工作是提供对一组相关项目或单个项目的访问。但它不处理不同实体之间的复杂查询。它提供可以被调用方法用于更复杂查询的数据? - Lews Therin
1
不应该关心存储库内部执行什么操作,您将测试其接口、外部契约。如果需要一个虚假的模拟存储库,您不必实际编写复杂的查询,因为您正在伪造结果。当然,您可以拥有在内部执行复杂操作的存储库。 - Jobo
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接