RSpec 新手:"更新属性 =>假"不被认可 [英] RSpec Newbie: "Update attributes => false" not being recognised

查看:40
本文介绍了RSpec 新手:"更新属性 =>假"不被认可的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

刚开始使用 RSpec.一切都很顺利,除了一个带有嵌套控制器的规范.

Just starting out with RSpec. Everything is going smoothly, except for one spec with nested controllers.

我试图确保当使用无效参数更新评论"资源(嵌套在帖子"下)时,它会呈现编辑"模板.我正在努力让 rspec 识别 :update_attributes => 错误触发器.如果有人有任何建议,他们将不胜感激.尝试以下代码:

I'm trying to ensure that when a 'comment' resource (nested under 'post') is updated with invalid parameters, it renders the 'edit' template. I'm struggling to get rspec to recognise the :update_attributes => false trigger. If anyone has any suggestions, they'd be very appreciated. Attempted code below:

  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.

推荐答案

这是一个很有趣的问题.一个快速的解决方法是简单地替换 Comment.stub 的块形式:

This is quite an interesting problem. A quick fix is to simply replace the block form of Comment.stub:

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

带有显式and_return:

Comment.stub(:find).with("12").\
  and_return(mock_comment(:update_attributes => false))

至于为什么这两种形式会产生不同的结果,这有点令人头疼.如果您使用第一种形式,您会看到当调用存根方法时,模拟实际上返回 self 而不是 false.这告诉我们它没有存根该方法(因为它被指定为一个空对象).

As to why these two forms should produce different results, that's a bit of a head-scratcher. If you play around with the first form you'll see that the mock is actually returning self instead of false when the stubbed method is called. That's tells us it hasn't stubbed the method (since it's specified as a null object).

答案是,当传入一个块时,块只在调用 stubbed 方法时执行,而不是在定义 stub 时执行.所以在使用块形式时,如下调用:

The answer is that when passing in a block, the block is only executed when the stubbed method is called, not when the stub is defined. So when using the block form, the following call:

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

正在第一次执行 mock_comment.由于 :update_attributes =>false 没有被传入,方法没有被存根,并且返回模拟而不是 false.当块调用 mock_comment 时,它返回 @mock_comment,它没有存根.

is executing mock_comment for the first time. Since :update_attributes => false is not being passed in, the method is not stubbed, and the mock is returned rather than false. When the block invokes mock_comment it returns @mock_comment, which doesn't have the stub.

相反,使用 and_return 的显式形式会立即调用 mock_comment.最好使用实例变量而不是每次都调用方法以使意图更清晰:

Contrariwise, using the explicit form of and_return invokes mock_comment immediately. It would probably be better to use the instance variable instead of calling the method each time to make the intent clearer:

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

这篇关于RSpec 新手:&quot;更新属性 =&gt;假"不被认可的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆