1

首先,我对此问题的开放性质表示歉意。然而,我已经瘫痪了好几个月,尽管同意搜索,仍然无法克服这一点。构建可测试的MVC3和EF 4.1应用程序

我一直在研究MVC/EF应用程序一段时间。我想了解如何设计和构建由Entity Framework(4.1)支持的可测试MVC3应用程序。您可以在hereherehere这个主题上看到几个问题。

我不想让它复杂化,但我希望它是一个可以增长的声音,松散耦合的设计。就我的理解,下面是非常最低限度所需的组件:

MVC应用程序
这是非常薄。尽可能少的逻辑在这里。我的观点具有尽可能少的条件逻辑,我的观点模型不过是POCO,而我的控制器只是简单地处理视图模型和领域模型之间的映射,并呼叫服务。

服务层+接口(单独的程序集)
这是我所有的业务逻辑去的地方。这样做的目标是能够掌控任何瘦客户端(表单应用程序,移动应用程序,Web服务),以暴露我的应用程序的内心。服务层的接口位于另一个程序集中。

核心工具/交叉+接口(单独的组件)
这是东西,我建立这不是具体到我的应用程序,而不是框架或我使用任何第三方插件的一部分。再次,这些组件的接口位于它们自己的组件中。

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

域模型(EF POCOs)
EF4生成的POCOs。其中的一些可以被扩展为方便起见,以其它嵌套属性或计算的特性(如Order.Total = Order.Details.Sum(d => d.Price)

IoC容器
这就是用于注射我的混凝土/假依赖(服务/实用程序)到MVC应用程序&服务。构造函数注入只用于整个。

这里就是我挣扎:

1)集成测试是适当的对单元测试。例如,一些程序集是否需要混合两者,或者是主要针对MVC应用程序的集成测试以及我的服务&实用程序的单元测试?

2)难道我打扰写存储库/域模型代码的测试吗?当然就POCO而言,这不适用。但是,当我延长我的POCO和计算属性时呢?

3)用于存储库的正确模式。我知道这是非常主观的,因为每次我看到这个讨论时,似乎每个人都有不同的方法。因此,很难确定要走哪条路。例如,我是否会推出自己的存储库,或者直接使用EF(DbContext)?

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

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

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

我认为这就够了。如果结果太开放了,让我知道,我很乐意关闭。但是,再次,我已经花了数月的时间试图独自一人解决这个问题,但没有运气。

回答

5

这是一个非常复杂的问题。您的每一点都足以成为一个单独的问题,因此我只写简短的摘要:

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

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

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

  4. 它完全依赖于以前的观点。如果您公开IQueryable或接受Expression<Func<>>的方法在内部传递给IQueryableyou cannot correctly mock the repository(您可以,但您仍然需要将每个单元测试与测试相同逻辑的集成测试进行配对)。 LINQ到实体是“副作用”/泄漏抽象。如果你完全包装仓库中的查询并使用你自己的声明性查询语言(规范模式),你可以嘲笑它们。

  5. 任何测试都比不测试更好。许多方法学期望高密度覆盖。 TDD甚至达到100%的测试覆盖率,因为测试总是先写入,没有测试就没有逻辑。这是关于您所遵循的方法,以及如果您需要针对代码段进行测试,您可以选择专业决策。

  6. 我不认为有任何“读这个,你会知道如何做到这一点”。这是软件工程和软件工程是一门艺术。在任何情况下都没有蓝图(在大多数情况下都不适用)。

+0

谢谢,拉迪斯拉夫。我知道这不是一个容易回答的问题,并且我感谢你无论如何都在刺探它。为了澄清,我可能会有一些愚蠢的存储库,并将LINQ-to-entities逻辑保留在我的服务层中。所以它真的会在我的服务层中承担很多责任(业务+查询逻辑)。这是否会导致它自己的问题 - 即对此进行权衡与为我的LINQ-to-entities逻辑创建存储库并使我的服务层严格遵守业务逻辑有什么关系?再次,我知道这是主观的,我只是想确保我理解这种权衡。 –

+0

_作为一个离题的方面说明,我想感谢你对SO社区的贡献,尤其是我的问题,因为你经常会回答我的很多问题,其中大部分似乎都需要很多时间和你的想法。它不会被忽视._ –

相关问题