Aca*_*uza 11 .net nhibernate unit-testing domain-driven-design entity-framework
对不起,我不知道存储库模式,单元测试和orm工具.
我一直在研究单元测试和存储库模式,得出了一些结论,我想知道我是不对的.
存储库模式有助于在控制器中替换单元测试,例如使用它,对吧?因为创建上下文(在EF中)或会话(在NH中)更难,对吧?存储库本身未经过测试?为什么?
使用EntityFramework或NHibernate与存储库模式,如果我想测试我的存储库,我需要进行集成测试?因为如果我使用我的上下文/会话的假实现,我没有进行真正的测试?因为上下文/会话本身就是存储库(我的意思是它们实现了添加,删除,编辑,GetById,GetAll等的真实逻辑)?
使用EF或NH的存储库模式就像一个包装器?(不仅是一个包装器,我知道这是域的导入概念.)
Dmi*_*try 14
存储库接口属于域层.但实现属于基础架构或数据访问层.通常不使用单元测试来测试此实现.它大量使用ORM API,因此单独测试存储库非常困难和浪费.此问题并非特定于存储库:不要模拟您不拥有的类型.
应使用真实ORM使用集成测试对存储库进行测试.在内存数据库中是一个非常流行的解决此问题的方法.
...因为如果我使用我的上下文/会话的假实现,我没有进行真正的测试?
即使你设法成功(我真的怀疑NHibernate的情况),你也会浪费你的时间.会话/上下文界面不受您的控制,您的测试只会重复您对真实事物如何工作的猜测.
因为上下文/会话本身就是存储库?
否.上下文/会话是UnitOfWork模式的实现.它不属于您的域名.这是基础设施.
使用EF或NH的存储库模式只是一个包装器?
存储库是重要的域概念,它不仅仅是一个"包装器".就像您的应用程序不是数据库的"包装器"一样.我认为DDD存储库接口定义应尽可能基于泛在语言,不应包含任何与ORM相关的单词或类型.
Lad*_*nka 11
在这种情况下,我会严格区分EF和NH,我不会在同一个问题中包含这两种技术.简单的NH更加成熟,并且具有可以更容易测试的代码的架构.同样在NH的情况下,你可以简单地将数据库切换到另一个(如SQLite),它仍然可以工作,在EF的情况下不一定是真的,其中切换数据库可以导致测试完全不同的应用程序 - 特别是如果您在MS和非MS数据库之间切换.
什么是存储库?让我们看看Martin Fowler的定义:
存储库在域和数据映射层之间进行调解,其作用类似于内存中的域对象集合.客户端对象以声明方式构造查询规范,并将它们提交给Repository以满足要求.可以从简单的对象集合中向对象添加对象或从对象库中删除对象,并且由存储库封装的映射代码将在后台执行适当的操作.从概念上讲,存储库封装了持久存储在数据存储中的对象集以及对它们执行的操作,从而提供了更加面向对象的持久层视图.存储库还支持在域和数据映射层之间实现清晰分离和单向依赖的目标.
很好的定义.现在想想以下目的DbSet:
Local属性来获取已加载的实体.IDbSet于域模型将使域模型依赖于技术 - EF.有问题吗?理论上是的,对于纯粹的是,但在99%中它确实不是问题,因为您需要更改API的情况很少见,即使您正确地分离API,它也总是涉及大的变化.DbSet是一个存储库.DbSet直接使用和将其包装到某个通用存储库之间的唯一区别是分离.这导致我以前对类似问题的回答 - 使用EF 4.1的通用存储库有什么意义
现在,您的应用程序中存储库的目的是什么?我看到你以前的问题,包括这一个,你有你的BaseRepository建立在实体框架之上.如果您认为这是一个基本存储库,它将是您的专业存储库的父级,用于您的域模型的聚合根,并且只公开与特定的公开实体类型相关的专用方法,那么是 - 您正在使用存储库模式,您需要它.但是如果你只是包装上下文和单一集并调用这个存储库,你最有可能只创建了带有可疑附加值的冗余层,因为这只是顶层的包装DbSet.
DbSet在这种情况下,只有一个场景,您的存储库(包装器)才有意义:
IQueryable(linq-to-entities)Expression<>并将其内部传递给IQueryalbe(linq-to-entities)这是唯一可以为您提供完全可模拟的存储库的场景=>您的上层可以轻松进行单元测试.您不打算单元测试存储库,也不打算模拟存储库中使用的上下文.存储库包装数据访问和映射逻辑 - 在存储库的情况下,唯一合理的测试是集成测试.这个场景有什么问题?你将失去LINQ的全部功能,你必须包装/重新实现EF中实现的一些方法和类型.这种存储库与使用存储过程包装数据访问时使用的存储库相同.
如果你不遵循这种情况,你的生活会更容易.您将拥有LINQ定义的查询,但您将无法对代码进行单元测试,因为没有mock/fake仍然会将查询评估为linq-to-entities.一旦你模拟DbSet或IQueryable你将使用linq-to-object,它是linq-to-entities的超集.您可以轻松编写一个查询,该查询将通过模拟传递测试DbSet但在运行时使用真实模式失败DbSet.这里更多的是关于这个问题,在这里是指将通过测试,但在运行时失败查询的例子.在这种情况下,您必须对存储库顶部使用linq-to-entities查询的所有方法使用集成测试(使用真实数据库).
| 归档时间: |
|
| 查看次数: |
2948 次 |
| 最近记录: |