如何使用 RSpec 在 CanCan 授权失败时测试响应代码?

10

我正在开发一个Rails项目,其中使用CanCan来授权我的资源。当用户未登录并尝试提交“talk”(通过ajax表单提交)时,CanCan会正确地抛出401作为响应,并显示{"status":"error","message":"You must be logged in to do that!"} (我已经使用firebug在浏览器中验证了这一点)。但是,在我的测试中,我得到的是302响应代码而不是401:

class TalksController < ApplicationController
  authorize_resource

  def create
    @talk = current_user.talks.build(params[:talk])

    respond_to do |format|
      if @talk.save
        response = { :redirect => talk_path(@talk) }
        format.html { redirect_to @talk, notice: 'Talk was successfully created.' }
        format.json { render json: response, status: :created,  }
      else
        format.html { render action: "new" }
        format.json { render json: @talk.errors, status: :unprocessable_entity }
      end
    end
  end
end

talks_controller_spec.rb:

describe TalksController do
  describe "POST create" do
    context "when not signed in" do
      it "should not assign talk" do
        post :create
        assigns[:talk].should be_nil
      end
      it "should respond with a 401" do
        post :create
        response.response_code.should == 401
      end
    end
  end
end

这里提供的第一个例子是成功的(assigns[:talk]没有被赋值),但第二个例子不成功:

1) TalksController POST create when not signed in should respond with a 401
     Failure/Error: response.response_code.should == 401
       expected: 401
            got: 302 (using ==)
     # ./spec/controllers/talks_controller_spec.rb:53:in `block (4 levels) in <top (required)>'

我不确定到底发生了什么。有没有一种方法可以测试实际返回给浏览器的响应代码?或者有更好的方法可以测试授权?


你可以尝试更改规范以读取 post :create, :format => :json,看看是否有帮助。 - zetetic
谢谢您的建议!不幸的是,即使我添加了 :format => :json,我仍然得到相同的 302 状态码。 - Matt McCormick
1
你看过测试日志了吗? - zetetic
1个回答

9

事实证明,我的项目通过以下功能从CanCan中解决了授权异常。由于该功能仅在请求为ajax时引发401(否则将重定向),因此我在浏览器中收到了401,但测试没有收到。

# Handle authorization exceptions
rescue_from CanCan::AccessDenied do |exception|
  if request.xhr?
    if signed_in?
      render json: {:status => :error, :message => "You don't have permission to #{exception.action} #{exception.subject.class.to_s.pluralize}"}, :status => 403
    else
      render json: {:status => :error, :message => "You must be logged in to do that!"}, :status => 401
    end
  else
    render :file => "public/401.html", :status => :unauthorized
  end
end

感谢zetetic提出的建议,让我检查我的测试日志,这揭示了请求方面的差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接