我同意多到上述情况,关于单元测试。不过,我认为重要的是要提出使用模拟存储库和单元测试不会达到与数据库集成测试相同级别的测试。
例如,我们的数据库通常会在模式中内置级联删除。在这种情况下,删除汇总中的主要实体会自动删除所有子实体。但是,这不会自动应用于未使用这些业务规则的物理数据库备份的模拟存储库(除非您将所有这些规则构建到模拟中)。这很重要,因为如果有人出现并改变我的模式的设计,我需要它来打破我的测试,以便我可以相应地调整代码/模式。我明白这是集成测试,而不是单元测试,但认为这是值得一提的。
我的首选选项是创建一个包含示例数据的主设计数据库(与您在Mocks中创建的数据类型相同)。在每次测试运行开始时,我都有一个自动化脚本,创建MasterDB的备份并将其恢复到“TestDB”(我的所有测试都使用该脚本)。这样,我在Master中维护一个清洁测试数据库,而不是在每次测试运行时重新创建它自己。我的测试可以播放数据并测试所有需要的场景。
当我调试应用程序时,我有另一个脚本备份并恢复主数据库到DEV数据库。我也可以在这里玩弄数据,而不用担心丢失我的样本数据。由于延迟等待重新创建数据库,我通常不会在每个会话中运行此特定脚本。我可能每天运行一次,然后全天玩耍/调试应用程序。例如,如果我从表中删除所有记录,作为调试的一部分,我会运行该脚本在完成后重新创建DevDB。
这些步骤听起来像是他们会为流程添加大量时间,但实际上 - 他们不会。我们的应用程序目前在3500个测试的区域中,其中约3000个在某个时间点访问数据库。在每次测试运行开始时,数据库备份和恢复通常需要大约10-12秒。而且由于整个测试套件仅在TFS签入时执行,所以我们不介意是否需要等待更长的时间。平均每天,我们的整个测试套件需要大约15-20分钟才能运行。
我理解并接受集成测试比单元测试慢得多(因为内在需要使用真实的数据库),但它更接近地代表了“真实世界”应用程序。例如,模拟存储库不会返回数据库错误代码,不会超时,不会锁定,不会耗尽磁盘空间等。
单元测试对于简单计算,基本业务规则等等,当然,它们绝对是大多数不涉及数据库(或其他资源)访问的操作的最佳选择。但我不认为它们与集成测试一样有价值 - 人们谈论了很多关于单元测试的内容,但关于集成测试的内容却很少。
我希望那些对单元测试充满激情的人会为此发火焰。这很好 - 我只是试图带来一些平衡,并提醒人们,在实现它们的时刻,那些充满了通过单元测试的项目仍然会失败。
我使用相同的datacontext嘲笑代码,它很好地工作 – 2009-01-06 14:45:40