2011-08-24 57 views
4

我經常看到它採用模擬在Rspec的代碼,就像這樣:爲什麼人們不能在Rspec中訪問數據庫?

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 

但他們爲什麼不通過get與ID數據庫=> 123添加Question,檢索,並摧毀它?這是最佳做法嗎?如果我不遵守規則,會發生什麼壞事?

回答

7

當你寫一個行爲測試(或單元測試),你想只測試特定的代碼部分,而不是整個堆棧。

爲了解釋這個更好的,你只是表達和測試「功能一應調用函數B與這些參數」,讓您在測試功能的,而不是函數B,爲您提供一個模擬。

這是一個重要的原因:

  1. 你不需要安裝在每個你建立你的代碼的機器上的數據庫,如果你開始使用製造機器(和/或持續集成,這是很重要)在您的公司擁有數百個項目。
  2. 如果功能B損壞或數據庫工作不正常,您可以獲得更好的測試結果,但功能A沒有測試失敗。
  3. 您的測試運行速度更快。
  4. 在每次測試之前擁有一個乾淨的數據庫總是很痛苦。如果之前的測試運行已停止,將會在數據庫中留下一個與該ID相關的問題?您可能會因爲重複的id而導致測試失敗,而實際上該功能正常運行。
  5. 在運行測試之前,您需要正確的配置。這是不是這樣一個令人難以置信的問題,但它是好得多,如果測試可以運行「開箱即用」,而無需配置數據庫連接,臨時測試文件的文件夾,用於測試電子郵件的東西的SMTP服務器,等等。

實際測試整個堆棧的測試稱爲「端到端測試」或「集成測試」(取決於測試的內容)。這些也很重要,例如,可以使用一套沒有模擬數據庫的測試來查看給定的應用程序是否可以安全地運行與開發過程中使用的不同的數據庫,並最終修復包含違規SQL語句的函數。

+0

我可以這樣說:如果我**必須在測試中訪問數據庫(例如,我無法在沒有數據庫中的某些文章的情況下測試關鍵字搜索功能),它應該是一個集成測試? –

+0

我會說,如果爲了測試某個特定的東西,你真的需要別的東西而不是你的代碼和測試套件(包括mock等),那麼測試實際上也在測試其他東西,所以這是一個集成測試。然而,確定什麼是應用程序的「正確」部分以及什麼不是,並且總是不可能僅僅基於mock編寫測試。在這些情況下,將這些測試放在一個不會「默認」運行的獨立套件中是一種好的做法。 –

2

其實很多人都這麼做,包括我在內。一般來說,由於測試是用來檢查行爲的,因此將數據庫條目插入某些人可能感覺有點不自然。

Question.new就足夠了,因爲它經歷了rails的有效方法,所以很多人傾向於使用它們,也因爲它們更快。

但的確,即使您開始使用工廠,也會有時候您可能會將數據插入到測試環境中。我個人並沒有看到這個問題。總體而言,在某些情況下,測試套件非常大,但不保存數據庫條目可能是一個相當有利的優勢。但是,如果速度不是你最關心的問題,我會說你不必擔心測試看起來如何,只要它的結構良好並符合要求。

順便說一句,你不需要銷燬測試數據,它會在測試結束後自動完成。因此,除非您正在檢查實際的刪除方法,否則請避免明確執行此操作。

+0

> *測試結束後自動完成*是否依賴安全?每個例子後數據庫都會乾淨?即使它意外停止? –

+0

是的,數據庫將在測試運行後清理。如果意外停止,它會在下一次運行時清理乾淨。說真的,你不需要關心清理。 – Spyros

相關問題