该库本身通常不进行测试?进行测试

2023-09-02 21:23:21 作者:念念不忘

我很抱歉,但我是新来的仓库模式,单元测试和ORM工具。

I'm sorry but I'm new to repositories patterns, unit tests and orm tools.

我一直在研究在单元测试和存储库模式,并且到达了在一些结论,我不知道如果我是正确的。

I've been researching on unit tests and the repository pattern, and arrived at some conclusions, I wonder if I'm right.

Repository模式有利于单元测试被替换控制器,利用它,例如,对不对?由于创建上下文(在EF)或会议(NH)的存根/假是很难的吧?该库本身没有进行测试?为什么呢?

The repository pattern facilitates unit testing to be replaced in controller that make use of it for example, right? Because create a stub/fake of context(in EF) or session(in NH) is harder, right? The repository itself is not tested? Why?

使用的EntityFramework或NHibernate的与存储库模式,如果我想测试我的仓库,我需要做集成测试?因为如果我用一个假的实现我的上下文/会话我没有做真正的测试?因为上下文/会议本身是存储库(我的意思是它们实现添加的真实逻辑,删除,编辑,GetById,GETALL,..)?

Using EntityFramework or NHibernate with repository pattern, if i want to test my repositories I need to do integration tests? Because if I use a fake implementation of my context/session I'm not doing real tests? Because the context/session itself is the repository (I mean they implement the real logic of Add, Remove, Edit, GetById, GetAll, ..)?

与EF或NH Repository模式是类似于包装? (不只是一个包装,我知道这是域的导入概念。)

The repository pattern with EF or NH is like a wrapper? (Not only a wrapper, I know this is a import concept of the domain.)

推荐答案

我会EF和NH之间严格区别在这种情况下,我将不包括这两种技术在同样的问题。简单NH较为成熟,具有结构导致code,可更容易地进行测试。另外,在箱NH的可以简单地切换数据库到另一个(像SQLite的)和它的工作仍然不具有对在壳体的EF其中切换数据库可以导致测试完全不同的应用是真实的是相同的 - 特别是如果你MS和非MS数据库之间进行切换。

I would strictly differ between EF and NH in this case and I would not include both technologies in the same question. Simple NH is more mature and has architecture leading to code which can be more easily tested. Also in case of NH you can simply switch the database to another one (like SQLite) and it will work still the same which doesn't have to be true in case of EF where switching database can result in testing completely different application - especially if you switch between MS and non-MS database.

什么是存储库?让我们看看 Martin Fowler的定义:

What is the repository? Let see Martin Fowler's definition:

一个仓库领域和数据映射层之间的中间,   像个内存中的域对象集合。客户对象   构建查询规范声明,并提交给   存储库的满意度。对象可以被加入并从除去   存储库,因为他们可以从对象的简单集合,   映射code的库封装将开展   幕后适当的操作。从概念上讲,信息库   封装对象集坚持一个数据存储和   执行的操作就过去了,提供一个更加面向对象的视图   持久层。信息库也支持的目标   实现了完全分离和单向依赖域之间   和数据映射层

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.

尼斯定义。现在想想,目的 DbSet

Nice definition. Now think about the purpose of DbSet:

它是作为在内存中的收藏?是的,你可以用它来从数据库中获取实体或使用本地属性来获取已加载的实体。 可以客户端查询规格声明?是的,它被称为LINQ到实体。 可以将对象中添加或删除从收藏?是的,可以。 是映射封装的?是的,它是。 是否有清晰的分离?在逻辑上是方面。在API方面没有因为暴露 IDbSet 来域模型将使域模型依赖于技术 -​​ EF。是不是问题?从理论上讲是的,纯粹是的,但99%是真的,不是因为情况下,你需要更改API是罕见的,它总是涉及即使你正确地分离的API大的变化的问题​​。 Does it act as in memory collection? Yes you can use it to get entities from database or use Local property to get already loaded entities. Can client query specifications declaratively? Yes it is called linq-to-entities. Can objects be added or removed as from collection? Yes it can. Is the mapping encapsulated? Yes it is. Is there clean separation? In terms of logic yes. In terms of API no because exposing IDbSet to domain model will make the domain model dependent on technology - EF. Is it problem? In theory yes, for purist yes but in 99% it is really not a problem because situation where you need to change the API is rare and it always involves big changes even if you correctly separated APIs.

DbSet 是一个资源库。使用 DbSet 直接包装成一些通用的存储库之间的唯一区别是分离的。这导致了我以前的答案类似的问题 - Generic资源库使用EF 4.1有什么意义

DbSet is a repository. The only difference between using DbSet directly and wrapping it into some generic repository is a separation. This leads to my former answer to similar question - Generic Repository With EF 4.1 what is the point

现在什么是您的应用程序库的目的是什么?我看到了你的previous问题,包括this 之一,你有你的 BaseRepository 建立在实体框架之上。如果你认真的意思是这是一个基础库,这将是父母对你的工作对总根为您的域模型和相关暴露只对特定暴​​露的实体类型,然后有专门的方法专门的仓库 - 您使用存储库模式,你需要它。但如果你只是包装环境和单套并调用这个仓库,你最有可能只创建冗余层可疑的附加价值,因为这只是包装器在 DbSet 的顶部。

Now what is a purpose of the repository in your application? I saw your previous questions including this one where you have your BaseRepository built on top of Entity framework. If you seriously mean this as a base repository which will be parent for your specialized repositories working on aggregate roots for your domain model and exposing specialized methods related only to specific exposed entity type then yes - you are using repository pattern and you need it. But if you are just wrapping context and single set and call this repository you most probably created only redundant layer with doubtful added value because that is just wrapper on top of DbSet.

只有一个场景,我们的资料库(DbSet 包装)会在这种情况下意义:

There is only single scenario where your repository (DbSet wrapper) will make sense in such case:

在该包装将永远不会暴露的IQueryable (LINQ到实体) 在该包装将永远不会接受防爆pression&LT;&GT; 并在内部传递给 IQueryalbe (LINQ -to-实体) The wrapper will never expose IQueryable (linq-to-entities) The wrapper will never accept Expression<> and pass it internally to IQueryalbe (linq-to-entities)

这是它会为您提供全面mockable库=>您的上层可以很容易地进行单元测试的唯一方案。你不会进行单元测试库,你是不是打算嘲笑在仓库使用环境。库包的数据访问和映射逻辑 - 唯一合理的测试,如果存储库是集成测试。这是什么情况下的问题呢?你会失去LINQ的整体力量,你将必须包装/重新实现一些方法和EF实现类型。如使用存储过程数据包访问时,使用这种存储库是一样的。

This is the only scenario which will offer you fully mockable repositories => your upper layer can be easily unit tested. You are not going to unit test repositories and you are not going to mock context used in repositories. Repositories wrap data access and mapping logic - the only reasonable tests in case of repositories are integration tests. What is problem of this scenario? You will lose whole power of LINQ and you will have to wrap / re-implement some methods and types implemented in EF. This kind of repositories is the same as used when wrapping data access using stored procedures.

如果你不按照该方案您的生活会更容易。你将不得不通过LINQ定义的查询,但你将无法进行单元测试code,因为没有模拟/假的,这将仍评估查询作为LINQ到实体。一旦你嘲笑 DbSet 的IQueryable 您将使用LINQ到对象,它是LINQ到实体的超集。你可以随便写,这将通过测试的嘲笑 DbSet 的查询,但在运行时失败了真正的 DbSet 。 Here更多的是关于这个问题,这里是查询的例子,这将通过测试,但在运行时失败。在这种情况下,你必须使用集成测试(与实际的数据库)的使用LINQ到实体查询您的仓库之上的所有方法。

If you don't follow that scenario your live will be much easier. You will have queries defined by LINQ but you will not be able to unit test the code because there is no mock / fake which will still evaluate queries as linq-to-entities. Once you mock DbSet or IQueryable you will use linq-to-object which is superset of linq-to-entities. You can easily write a query which will pass a test on mocked DbSet but fail at runtime with a real DbSet. Here is more about this problem and here is the example of query which will pass the test but fail at runtime. In this case you must use integration tests (with real database) for all methods using linq-to-entities queries on top of your repositories.

相关推荐