7

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

来自应用程序的 DinnerRepository :回购图片

来自测试的FakeDinnerRepository假图片

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

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

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

问题:

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

2 回答 2

4

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

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

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

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

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

希望这可以帮助!

于 2009-10-10T20:38:28.393 回答
2

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

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

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

于 2009-12-30T20:00:01.757 回答