2011-08-11 53 views
0

我想弄清楚我的RSpec測試是否適用於我的控制器,但它不工作,我需要一些幫助來搞清楚它。RSpec嘲笑ActiveRecord的問題首先找到哪裏

我Rspec的是:

before(:each) do 
    @topic = mock_model(Topic, :update_attributes => true) 
    Topic.stub!(:where).with({:slug=>"some-slug"}).and_return(@topic) 
    with_valid_user 
    end 

    it "should find topic and return object" do 
    Topic.should_receive(:where).with("some-slug").and_return(@topic) 
    put :update, :topic_slug => "some-slug", :topic => {} 
    end 

我試圖測試控制器邏輯是:

def get_topic 
    @topic = Topic.where(:slug => params[:topic_slug]).first 
    @topic 
    end 

但我得到的輸出是:

Failure/Error: Topic.stub!(:where).with({:slug=>"some-slug"}).first.and_return(@topic) 
NoMethodError: 
    undefined method `first' for #<RSpec::Mocks::MessageExpectation:0x104c99910> 
# ./spec/controllers/topics_controller_spec.rb:41 

顯然,似乎是要求「第一」的方法。我知道在這種情況下有點多餘,所以我可以將其刪除,但我不知道如何正確使用(針對此場景)。

任何人都可以幫我填補我的空洞嗎?

更新:

我加入了[@topic]數組作爲答案的建議,但現在我得到的錯誤:

Failure/Error: put :update, :topic_slug => "some-slug", :topic => {} 
     Mock "Topic_1001" received unexpected message :slug with (no args) 

對於此代碼:

def get_topic 
    @topic = Topic.where(:slug => params[:topic_slug]).first 
    @topic 
    end 

參數不能改變(至少不是微不足道的)。更多的幫助非常感謝!

回答

3

改變這一行

Topic.should_receive(:where).with("some-slug").and_return(@topic)

這個

Topic.should_receive(:where).with("some-slug").and_return([@topic])

你期望陣列,但返回一個元素。

+0

我做了你所建議的改變,但是現在我得到了:'失敗/錯誤:put:update,:topic_slug =>「some-slug」,:topic => {} 模擬「Topic_1001」收到意外消息: slug with(no args)' - 我認爲是因爲'@topic = Topic.where(:slug => params [:topic_slug])。first'。 任何想法如何解決? – Ash

2

stub_chain是一種代碼味道,應視爲最後的手段。它將您的規範緊密地與實現細節聯繫起來,實現細節可以通過重構進行更改。

我建議是這樣的:

Topic.should_receive(:with_slug).and_return(@topic) 

然後添加一個with_slug方法Topic,你是好去。