我经常看到在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
检索它,并将其销毁?这是最佳做法吗?如果我不遵守规则,会发生什么不好的事情吗?
答案 0 :(得分:7)
当您编写行为测试(或单元测试)时,您尝试仅测试代码的特定部分,而不是整个堆栈。
为了更好地解释这一点,你只是表达并测试“函数A应该用这些参数调用函数B”,所以你要测试函数A而不是函数B,你为它提供了一个模拟。
这很重要,原因有很多:
实际测试整个堆栈的测试称为“端到端测试”或“集成测试”(取决于它测试的内容)。这些也很重要,例如,可以使用一组没有模拟数据库的测试来查看给定应用程序是否可以安全地运行与开发期间使用的DB不同的DB,并最终修复包含有问题的SQL语句的函数。
答案 1 :(得分:2)
实际上,很多人都这样做,包括我。一般来说,由于测试是为了检查行为,因此将数据库条目插入某些人会觉得有点不自然。
Question.new就足够了,因为它无论如何都要通过有效的rails方法,所以很多人都倾向于使用它们,也因为它们更快。
但是,实际上,即使您开始使用工厂,也有时候您可能会将数据插入到测试环境中。我个人认为这没有任何问题。
总的来说,在某些情况下,测试套件非常大,不保存数据库条目是非常有利的。但如果速度不是你最关心的问题,我会说你不必担心测试看起来如何,只要它构造得很好而且非常重要。
顺便说一句,你不需要破坏测试数据,它会在测试结束后自动完成。因此,除非您检查实际的删除方法,否则请避免明确地执行此操作。