2011-01-14 3 views
4

RSpec으로 시작하기. 중첩 된 컨트롤러가있는 하나의 사양을 제외하면 모든 것이 원활하게 진행됩니다.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)) 

을, 그건 머리 - 약간이다 scratcher. 첫 번째 형식으로 놀아 본다면 모의 된 메서드가 호출되었을 때 false이 아닌 self이 실제로 반환된다는 것을 알 수 있습니다. 이것은 null 메소드로 메소드를 스텁하지 않았 음을 알려줍니다.

블록을 전달할 때 스텁이 정의 된 시점이 아니라 스텁 된 메서드가 호출 될 때만 블록이 실행된다는 것이 답입니다. 그래서, 다음 호출 블록 형태를 사용하는 경우 :

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

관련 문제