2009-01-06 68 views
6

我想用测试开始一个新的MVC项目,我认为最好的方法去有2个数据库。 1用于测试,1用于运行应用程序并使用它(同时测试真的,因为它不是生产)。LINQ和SQL数据库的ASP.NET MVC TDD

对于测试数据库,我正在考虑将创建表脚本和填充数据脚本放入测试设置方法中,然后在拆卸方法中删除所有这些。

虽然我将使用Linq到SQL,但我不认为这会允许我这样做?

如果我想这样做,我必须去ADO路线吗?或者我应该只使用模拟对象并将数据存储为数组或其他东西?

有关最佳实践的任何提示?

Jeff如何为StackOveflow执行此操作?

回答

4

我所做的是为DataContext包装器定义一个接口,并使用DataContext的包装实现。这使我可以在我的测试中使用替代的,假的DataContext实现(或者更简单地模拟它)。这将我的单元测试完全抽象出数据库。我在http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx处发现了一些入门代码,尽管我已经对它进行了扩展,以便它处理实体类上的验证实现。

我还应该提到,我有一个单独的QA登台服务器,所以现场测试整个系统。我只是在我的单元测试中不使用实际的数据库。

+0

我使用相同的datacontext嘲笑代码,它很好地工作 – 2009-01-06 14:45:40

1

您可能希望找到一些其他方法来实际触及单元测试的数据库,因为它需要更多时间。这就是说,你有没有考虑过使用Migrations创建/删除你的表而不是使用sql脚本? RikMigrations是我一直用来创建我的数据库,所以我可以轻松地修改我的所有代码在一个地方。 Justin Etheredgeusing RikMigrations上有很棒的文章。

1

我同意多到上述情况,关于单元测试。不过,我认为重要的是要提出使用模拟存储库和单元测试不会达到与数据库集成测试相同级别的测试。

例如,我们的数据库通常会在模式中内置级联删除。在这种情况下,删除汇总中的主要实体会自动删除所有子实体。但是,这不会自动应用于未使用这些业务规则的物理数据库备份的模拟存储库(除非您将所有这些规则构建到模拟中)。这很重要,因为如果有人出现并改变我的模式的设计,我需要它来打破我的测试,以便我可以相应地调整代码/模式。我明白这是集成测试,而不是单元测试,但认为这是值得一提的。

我的首选选项是创建一个包含示例数据的主设计数据库(与您在Mocks中创建的数据类型相同)。在每次测试运行开始时,我都有一个自动化脚本,创建MasterDB的备份并将其恢复到“TestDB”(我的所有测试都使用该脚本)。这样,我在Master中维护一个清洁测试数据库,而不是在每次测试运行时重新创建它自己。我的测试可以播放数据并测试所有需要的场景。

当我调试应用程序时,我有另一个脚本备份并恢复主数据库到DEV数据库。我也可以在这里玩弄数据,而不用担心丢失我的样本数据。由于延迟等待重新创建数据库,我通常不会在每个会话中运行此特定脚本。我可能每天运行一次,然后全天玩耍/调试应用程序。例如,如果我从表中删除所有记录,作为调试的一部分,我会运行该脚本在完成后重新创建DevDB。

这些步骤听起来像是他们会为流程添加大量时间,但实际上 - 他们不会。我们的应用程序目前在3500个测试的区域中,其中约3000个在某个时间点访问数据库。在每次测试运行开始时,数据库备份和恢复通常需要大约10-12秒。而且由于整个测试套件仅在TFS签入时执行,所以我们不介意是否需要等待更长的时间。平均每天,我们的整个测试套件需要大约15-20分钟才能运行。

我理解并接受集成测试比单元测试慢得多(因为内在需要使用真实的数据库),但它更接近地代表了“真实世界”应用程序。例如,模拟存储库不会返回数据库错误代码,不会超时,不会锁定,不会耗尽磁盘空间等。

单元测试对于简单计算,基本业务规则等等,当然,它们绝对是大多数不涉及数据库(或其他资源)访问的操作的最佳选择。但我不认为它们与集成测试一样有价值 - 人们谈论了很多关于单元测试的内容,但关于集成测试的内容却很少。

我希望那些对单元测试充满激情的人会为此发火焰。这很好 - 我只是试图带来一些平衡,并提醒人们,在实现它们的时刻,那些充满了通过单元测试的项目仍然会失败。

+0

有趣的,但绝对切线..加上字母TFS发送了一个颤栗我的脊椎! – Lloyd 2012-01-26 12:52:37