【问题标题】:Dependency injection in NerdDinner - actually testing your repository or modelNerdDinner 中的依赖注入 - 实际测试您的存储库或模型
【发布时间】:2009-10-10 15:23:41
【问题描述】:

考虑一个处理依赖注入的初学者。我们正在分析 NerdDinner 中的两个相关类。

DinnerRepository 来自应用程序:

FakeDinnerRepository 来自测试:

它们实现了不同的逻辑,这当然是必要的,因为这里的关键思想是实现IDinnerRepository,并提供不同的实现和私有成员。

我知道测试是针对控制器的,但我担心数据访问逻辑有两种不同的实现。考虑使用任何类型的 ORM、ADO.NET、SubSonic 或您喜欢的任何类型的数据访问的任何项目。是的,您可以设置您的假存储库以匹配真实存储库。

我担心的是,随着时间的推移,真实仓库中的实现细节会发生变化。可能是输入错误,或者 查询 中有一些其他重要的实现细节更改。这导致模型中的假货和真实回购之间的逻辑可能不匹配。担心的是真正的 repo 和 test repo 的实现不同步。

问题:

  • 在这种情况下,您将如何测试模型?
  • 是否适合测试模型?
  • 确保您的测试跟上业务逻辑的实施是否符合纪律?

【问题讨论】:

    标签: unit-testing dependency-injection inversion-of-control nerddinner


    【解决方案1】:

    这可能不是您问题的完整答案,但我会尽力解决。

    接口 - 在本例中为 IDinnerRepository - 应被视为合约。这意味着任何实现都必须履行这个合同。如果方法是 FindAllDinners(),那么这基本上就是它应该做的。用于单元测试的虚假存储库通常比真实存储库简单很多(例如使用字典),因此跟上真实实现不应该被视为问题,而应将其视为要求。

    首先存在虚假存储库的原因是测试。基本上,所有可以测试的东西都应该被测试。将数据库排除在外是内存中假存储库的重点。数据访问不是测试的重点,所以我们替换它。假存储库的设置和使用速度要快得多,我们可以轻松确保存储库处于测试代码通过所需的状态。

    所以你要做的就是在你的单元测试中向模型传递你的假存储库的副本,并确保模型代码中发生的任何事情都反映在假存储库中。

    我想您会发现,在实践中,保持存储库同步不会有问题。如果需求发生变化,您将更改接口并且两个实现都需要更改。如果意图发生变化,您可能会达到单元测试开始中断的地步。

    希望这会有所帮助!

    【讨论】:

    • 谢谢符文。这就说得通了。我想问题的基础是:你应该测试你的数据访问吗?听起来你在说“不”。
    • 这实际上是我作为一名 TDD 新手而苦苦挣扎的事情之一。按照我目前的理解,您的单元测试应该不理会实际的数据访问,而进行集成测试来检查实际数据访问是否正常工作显然是个好主意。这些集成测试会更慢,但这应该是可以接受的,因为它们可能不会像“纯”单元测试那样频繁地运行。
    【解决方案2】:

    FakeDinnerRepository 用于测试需要 IDinnerRepository 的代码毫无价值。不要测试 DinnerRepository 本身。如果我们使用真正的晚餐存储库来测试诸如 DinnerController 之类的东西,我们不仅会测试 DinnerController 的功能,还会测试数据访问本身。虽然当然应该测试数据访问位,但它们不应该在晚餐控制器的测试中进行测试。

    测试您的数据访问是一个颇具争议的话题。我相信大多数人将其排除在单元测试之外的原因仅仅是它需要更长的时间来执行。必须查询数据库会给您的测试增加大量时间,这是大多数开发人员不愿忍受的。

    您的数据访问是在单元测试还是更正式的功能测试中进行测试取决于您。但它肯定需要测试。就个人而言,我很喜欢对数据访问层进行事务性单元测试。只要确保您只测试您的查询,而不是测试您的 ORM 是否按预期工作(这是 ORM 的工作)。

    【讨论】:

      猜你喜欢
      • 2010-11-27
      • 2019-11-27
      • 2014-01-09
      • 1970-01-01
      • 2012-12-23
      • 2018-05-02
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      相关资源
      最近更新 更多