为什么人们不在Rspec中访问数据库?

时间:2011-08-24 17:09:00

标签: ruby-on-rails rspec

我经常看到在Rspec中使用mock的代码,如下所示:

describe "GET show" do
  it "should find and assign @question" do
    question = Question.new

    Question.should_receive(:find).with("123").and_return(question)
    get :show, :id => 123

    assigns[:question].should == question
  end
end

但为什么他们不添加Question id => 123在数据库中,通过get检索它,并将其销毁?这是最佳做法吗?如果我不遵守规则,会发生什么不好的事情吗?

2 个答案:

答案 0 :(得分:7)

当您编写行为测试(或单元测试)时,您尝试仅测试代码的特定部分,而不是整个堆栈。

为了更好地解释这一点,你只是表达并测试“函数A应该用这些参数调用函数B”,所以你要测试函数A而不是函数B,你为它提供了一个模拟。

这很重要,原因有很多:

  1. 您不需要在构建代码的每台计算机上安装数据库,如果您在公司中使用数百个项目的构建计算机(和/或持续集成),这一点非常重要。
  2. 您可以获得更好的测试结果,如果功能B中断,或者数据库无法正常工作,则不会在功能A上出现测试失败。
  3. 您的测试运行得更快。
  4. 在每次测试之前拥有一个干净的DB总是很痛苦。如果先前的测试运行停止,在数据库上留下具有该ID的问题怎么办?您可能会因为重复ID而导致测试失败,而实际上该功能正常运行。
  5. 在运行测试之前,您需要正确配置。这不是一个令人难以置信的问题,但如果测试可以“开箱即用”运行,而不必配置数据库连接,临时测试文件的文件夹,用于测试电子邮件的SMTP服务器等等,那就更好了。
  6. 实际测试整个堆栈的测试称为“端到端测试”或“集成测试”(取决于它测试的内容)。这些也很重要,例如,可以使用一组没有模拟数据库的测试来查看给定应用程序是否可以安全地运行与开发期间使用的DB不同的DB,并最终修复包含有问题的SQL语句的函数。

答案 1 :(得分:2)

实际上,很多人都这样做,包括我。一般来说,由于测试是为了检查行为,因此将数据库条目插入某些人会觉得有点不自然。

Question.new就足够了,因为它无论如何都要通过有效的rails方法,所以很多人都倾向于使用它们,也因为它们更快。

但是,实际上,即使您开始使用工厂,也有时候您可能会将数据插入到测试环境中。我个人认为这没有任何问题。

总的来说,在某些情况下,测试套件非常大,不保存数据库条目是非常有利的。但如果速度不是你最关心的问题,我会说你不必担心测试看起来如何,只要它构造得很好而且非常重要。

顺便说一句,你不需要破坏测试数据,它会在测试结束后自动完成。因此,除非您检查实际的删除方法,否则请避免明确地执行此操作。