2011-01-14 9 views
4

RSpecでちょうど始まります。ネストされたコントローラを持つ1つの仕様を除いて、すべてがスムーズに進んでいます。RSpec Newbie: "属性の更新=> false"が認識されない

「コメント」リソース(「投稿」の下にネストされている)が無効なパラメータで更新されると、「編集」テンプレートが表示されるようにしています。私はrspecに:update_attributes => falseトリガを認識させるのに苦労しています。誰かが何か提案があれば、とても感謝しています。未遂以下のコード:

def mock_comment(stubs={}) 
    stubs[:post] = return_post 
    stubs[:user] = return_user 
    @mock_comment ||= mock_model(Comment, stubs).as_null_object 
    end 

    describe "with invalid paramters" dog 
    it "re-renders the 'edit' template" do 
     Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) } 
     put :update, :post_id => mock_comment.post.id, :id => "12" 
     response.should render_template("edit") 
    end 
    end 

とコントローラ:

def update 
    @comment = Comment.find(params[:id]) 
    respond_to do |format| 
     if @comment.update_attributes(params[:comment]) 
     flash[:notice] = 'Post successfully updated' 
     format.html { redirect_to(@comment.post) } 
     format.xml { head :ok } 
     else 
     format.html { render :action => "edit" } 
     format.xml { render :xml => @comment.errors, :status => :unprocessable_entity } 
     end 
    end 

    end 

そして最後に、エラーが:

Failure/Error: response.should render_template("edit") 
    expecting <"edit"> but rendering with <"">. 
    Expected block to return true value. 

答えて

5

これは非常に興味深い問題です。明示的なand_return

Comment.stub(:find).with("12") { mock_comment(:update_attributes => false) } 

:クイックフィックスは、単にComment.stubのブロック形式を交換することである

これら二つの形式が異なる結果を生成しなければならない理由として
Comment.stub(:find).with("12").\ 
    and_return(mock_comment(:update_attributes => false)) 

、それは頭部の少しです詐欺師。最初のフォームで試してみると、モックは実際にはfalseの代わりにselfを返すことがわかります。これは、メソッドをスタブしていないことを示しています(ヌルオブジェクトとして指定されているため)。

答えは、ブロックを渡すときに、スタブが定義されているときではなく、スタブ付きメソッドが呼び出されたときだけブロックが実行されることです。ブロック形式を使用するときに、次の呼び出し:

put :update, :post_id => mock_comment.post.id, :id => "12" 

は初めてmock_commentを実行しています。 :update_attributes => falseが渡されていないので、メソッドはスタブされず、falseではなくモックが返されます。ブロックがmock_commentを呼び出すと、@mock_commentが返されます。スタブはありません。

逆に、and_returnの明示的な形式を使用すると、すぐにmock_commentが呼び出されます。おそらく意図明確にするための方法を毎回呼び出すのではなく、インスタンス変数を使う方が良いでしょう:

it "re-renders the 'edit' template" do 
    mock_comment(:update_attributes => false) 
    Comment.stub(:find).with("12") { @mock_comment } 
    put :update, :post_id => @mock_comment.post.id, :id => "12" 
    response.should render_template("edit") 
end 
+0

優れ、徹底的に、明確な応答。どうもありがとう。 :-) – PlankTon

関連する問題