2011-12-04 62 views
2

我有一個TopicsController,用new行動:重構在RSpec的控制器規格嘲笑

def new 
    @section = Section.find(params[:section_id]) 
    @topic = @section.topics.build 
end 

雖然試圖測試這個簡單的行爲,我結束了相當難看和強大的模擬結構

describe "#new" do 
    it "builds a topic with a given section" do 
    new_topic = mock_model(Topic) 
    topics = mock('topics') 
    topics.should_receive(:build).and_return(new_topic) 

    section = mock_model(Section) 
    section.should_receive(:topics).and_return(topics) 

    Section.should_receive(:find).with("1").and_return(section) 
    get :new, :section_id => 1 

    assigns[:topic].should == new_topic 
    end 
end 

我想讓這段代碼更簡單,但我不知道如何。我無法擺脫@section模擬,它必須返回一些特定的鏈接.topics.build調用,以允許我設置一個期望。

有沒有更簡單的方法來做到這一點?我正在使用RSpec 2.7。

回答

4
describe TopicsController do 
    specify :new do 
    section = stub_chain(:topics, :build).and_return(:new_topic) 
    Section.should_receive(:find).with(1).and_return(section) 

    get :new, section_id: 1 

    assigns_should_match section: section, topic: :new_topic 
    end 
end 

def assigns_should_match(h) 
    h.each { |k,v| assigns[k].should == v } 
end 
-4

控制器規格是不必要的痛苦,因爲你找到了。相反,寫一個黃瓜場景(用真實的物體,而不是嘲笑)。

+1

黃瓜不是這個問題的解決方案。黃瓜是用於驗收測試(或集成測試,如果這是你真正想要使用它),不應該用於測試控制器。你最終會因爲錯誤的事情而使用黃瓜進行較慢和較少維護的測試。 – twe4ked

+0

@odin集成測試(即黃瓜故事)實際上是大多數情況下測試控制器的唯一可行方法(異常*可能適用於API端點的控制器)。一般來說,Rails控制器不需要單元測試(只有模型和類似的對象);事實上,控制器單元測試往往會測試錯誤的東西,因此他們會讓你認爲你的應用程序在沒有測試的時候經過了很好的測試。所以是的...黃瓜*是在這裏適當的解決方案。 –