构建可测试的MVC3& EF 4.1应用程序

时间:2011-11-09 05:34:58

标签: asp.net-mvc unit-testing entity-framework architecture

首先,我为这个问题的开放性质道歉。然而,我已经瘫痪了几个月,尽管经过同意搜索,仍然无法超越这个。

我一直在研究MVC / EF应用程序。我试图了解如何设计和构建由Entity Framework(4.1)支持的可测试的MVC3应用程序。您可以看到我就主题hereherehere提出的一些问题。

我试图不要过度复杂化,但我希望它能够成为一种声音松散耦合的设计。我理解它的方式,以下几乎是最不需要的组件:

MVC app
非常很薄。尽可能少的逻辑在这里。我的视图具有尽可能少的条件逻辑,我的视图模型永远不会超过POCO,我的控制器只是处理视图模型和域模型之间的映射,并调用服务。

服务层+接口(单独的程序集)
这就是我所有业务逻辑的所在。这样做的目的是能够在此基础上打击任何瘦客户端(表单应用程序,移动应用程序,Web服务)以暴露我的应用程序的内容。服务层的接口位于另一个程序集中。

核心实用程序/横切+接口(单独的程序集)
这是我构建的不是我的应用程序特有的东西,但不是框架或我正在使用的任何第三方插件的一部分。同样,这些组件的接口也位于它们自己的程序集中。

存储库(EF上下文)
这是我的域模型和我的数据库之间的接口。我的服务层使用它来通过域模型检索/修改我的数据库。

域名模型(EF POCO)
EF4生成了POCO。其中一些可以为了方便其他嵌套属性或计算属性(例如Order.Total = Order.Details.Sum(d => d.Price)

而扩展

IoC容器
这是用于将我的具体/假依赖(服务/实用程序)注入MVC​​ app&服务。构造函数注入仅在整个过程中使用。

这是我在努力的地方:

1)当集成测试适合单元测试时。例如,某些组件是否需要两者的混合,或者是主要用于MVC应用程序的集成测试和用于我的服务的单元测试。事业吗?

2)我是否打算针对存储库/域模型代码编写测试?当然,对于POCO,这是不适用的。但是当我扩展我的POCO w /计算属性时呢?

3)用于存储库的正确模式。我知道这是非常主观的,因为每当我看到这个讨论时,似乎每个人都有不同的方法。因此,很难弄清楚要走哪条路。例如,我可以滚动自己的存储库,还是直接使用EF(DbContext)?

4)当我为我的服务编写测试时,我是否会模拟我的存储库,或者我是否使用SQL Lite来构建模拟数据库并对其进行测试? (见辩论herehere)。

5)这是一个全有或全无的事情,如果我做任何测试,我应该测试一切吗?或者,是否任何测试都比没有测试更好?如果是后者,哪个更重要的领域首先击中(我在考虑服务层)?

6)是否有任何好的书籍,文章或示例应用程序可以帮助我回答大部分问题?

我认为现在已经够了。如果这最终过于开放,请告诉我,我很乐意关闭。但是,我已经花了几个月的时间试图自己解决这个问题而没有运气。

1 个答案:

答案 0 :(得分:5)

这是一个非常复杂的问题。你的每一点都足够大,可以作为一个单独的问题,所以我只会写一些简短的摘要:

  1. 集成测试和单元测试不会互相替换。如果您想要经过良好测试的应用程序,您总是需要两者。单元测试用于单独测试逻辑(通常借助于模拟,存根,假货等),而集成测试用于测试组件是否正常工作(=没有模拟,存根或伪造)。何时使用集成测试以及何时使用单元测试实际上取决于您正在测试的代码以及您正在遵循的开发方法(例如TDD)。

  2. 如果你的POCO包含任何逻辑,你应该为它们编写单元测试。存储库中的逻辑通常严重依赖于数据库,因此模拟上下文并在没有数据库的情况下测试它们通常是无用的,因此您应该使用集成测试来覆盖它们。

  3. 这实际上取决于您对存储库的期望。如果它只是愚蠢的DbContext / DbSet包装器,则存储库的值为零,并且它很可能不会使您的代码单元可测试,如某些引用的争论中所述。如果它包装查询(上层没有LINQ到entites),则公开对聚合根的访问,那么存储库的含义就是正确分离数据访问并暴露可模拟的接口。

  4. 完全取决于前一点。如果您公开IQueryable或接受Expression<Func<>>传递给IQueryable内部you cannot correctly mock the repository的方法(您可以,但您仍然需要将每个单元测试与集成测试配对相同的逻辑) 。 LINQ-to-entities是“副作用”/漏洞抽象。如果您完全将查询包装在存储库中并使用您自己的声明性查询语言(规范模式),您可以模拟它们。

  5. 任何测试都比没有测试好。许多方法都需要高密度覆盖。 TDD甚至达到100%的测试覆盖率,因为测试总是先编写,没有测试就没有逻辑。如果您需要对代码进行测试,那就是您遵循的方法以及您的专业决策。

  6. 我认为没有“读过这个,你会知道怎么做”。这是软件工程和软件工程是一门艺术。没有蓝图在每种情况下都有效(在大多数情况下都没有)。