2012-05-31 51 views
21

我只是好奇在哪裏人們傾向於使用FactoryGirl.build_stubbed和他們在編寫RSpec specs時使用double。也就是說,是否有最佳實踐,例如「在相應的模型規格中只使用FactoryGirl方法?」在哪裏使用`FactoryGirl.build_stubbed`以及在哪裏使用RSpec的`mock` /`double`

當您在spec/models/bar_spec.rb中發現自己使用FactoryGirl.create(:foo)時它是否會產生代碼異味?

如果您在spec/models/bar_spec.rb中使用FactoryGirl.build_stubbed(:foo),它是否會減少代碼異味?

如果您在foos_controller_spec.rb中使用FactoryGirl.create(:foo),是否會產生代碼異味?

如果您在foos_controller_spec.rb中使用FactoryGirl.build_stubbed(:foo),它會減少代碼味嗎?

如果您在spec/decorators/foo_decorator_spec.rb中使用FactoryGirl.build_stubbed(:foo),是否會產生代碼異味?

對不起,有很多問題!我很想知道其他人如何在單元測試隔離和麪向對象的設計最佳實踐中劃清界限。

謝謝!

+0

我個人甚至不知道'FactoryGirl.build_stubbed'。可能這就解釋了缺乏答案。術語「代碼味道」的這種或高主觀性。 –

回答

17

我相信有一些最佳實踐可以指導我們考慮何時使用mock(本例中爲「雙打」)與整合與真實依賴關係(本例中爲「工廠」)。關於測試的一本非常不錯的書(使用Java示例)描述了測試驅動開發的目的,我認爲這對於在Rails應用程序中進行測試的討論非常有幫助。它描述了測試的意圖如下:

......我們在測試驅動開發中的意圖是使用模擬對象來展現對象之間的關係。

Freeman,Steve; Pryce,Nat(2009-10-12)。面向對象的軟件越來越多,以測試爲導向(Kindle位置3878-3879)。培生教育(美國)。 Kindle版。

如果我們考慮這種強調使用測試驅動開發的方式,不僅要防止我們引入迴歸,而且要幫助我們考慮代碼的接口和與其他對象之間的關係,自然在許多情況下使用模擬。我將描述這如何適用於下面的具體問題。首先,根據我們在模型測試中是使用模擬對象還是真實依賴關係 - 如果我們測試Foo類和它對Bar的依賴關係,我們可能想用Bar替換模擬對象。通過這種方式,我們將清楚地看到耦合到Bar的級別,因爲我們必須模擬將要調用的方法。如果我們發現我們對Bar的模擬很複雜,那麼這可能表明我們應該重構Foo和Bar,這樣他們就不會互相耦合了。

從這個意義上說,Factory.createFactory.build_stubbed具有相同的效果,可以避免使相關類顯式依賴,我認爲它們都是臭的,Factory.create是兩個選項中較慢的。

在我的測試中,我傾向於不要太在意模擬控制器中的外部依賴關係。我知道這比完全嘲諷要慢,而且你沒有使控制器與模型耦合的好處,但是編寫測試的速度更快,而且我通常不擔心要清楚控制器與他們管理的持久記錄之間的關係。只要你遵循「瘦身控制器」的模式,無論如何都不應該有過於擔心的邏輯。如果我們需要在這裏指定一個「測試氣味」的級別,我會說它比一些依賴於其他工廠的模型測試少一點臭。

我會傾向於至少擔心裝飾者,他們裝飾類的工廠依賴。這是因爲根據定義,裝飾器應該保持與它們裝飾的類相同的接口。裝飾通常通過某種形式的繼承來實現,無論是通過使用method_missing委託給裝飾者,還是通過裝飾者的顯式子類來實現。正因爲如此,如果裝飾器與它所裝飾的東西的界面偏離太多,你就會破壞像Liskov Substitution這樣的好的面向對象編程的其他規則。只要你的裝飾沒有通過違背良好繼承的規則來實現,與你裝飾的類的耦合已經存在,所以如果你對裝飾物的測試依賴於持久或殘留物,它並沒有讓事情變得更糟糕它裝飾的東西的工廠。您可以在裝飾工測試中與工廠發瘋,這與IMO無關。

我認爲重要的是要注意,即使您在大多數情況下更喜歡mock,您仍應該有一些使用真正依賴關係的集成測試。你會發現它們涵蓋了特定的高價值案例,其中孤立的單元測試提供了更多類別提供的功能。

無論如何,我有時會違反上述所有規則,它們只是我在寫作測試中使用的一些準則。我期待着聽到其他人在測試中如何使用工廠(build_stubbed和真正持久)與模擬對象(雙打)。

+1

棒極了!真的很感激它。關於Rails中的集成測試 - 您發現自己在哪個級別測試不同對象是否實際上正在使用其他對象的正確接口?我經常看到的例子是瀏覽器級別的測試(水豚,硒等)。是否有更好的方法來進行更具體的集成測試(模型之間)?還是應該甚至有必要? –

相關問題