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

发布于 2024-12-08 14:04:25 字数 1623 浏览 1 评论 0原文

我正在开发一个 Rails 项目,在该项目中我使用 CanCan 来授权我的资源。当用户未登录并尝试提交“谈话”(通过 ajax 表单提交)时,CanCan 会正确地引发 401 错误 {"status":"error","message":"You must be Logged来做到这一点!”} 作为响应(我已经使用 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

此处包含的第一个示例是成功的(分配 [: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)>'

我不确定这是怎么回事。有没有办法可以测试返回到浏览器的实际响应代码?或者有更好的方法来测试授权?

I'm working on a rails project in which I use CanCan to authorize my resources. When a user is not signed in and tries to submit a "talk" (via an ajax form submission), CanCan correctly raises a 401 with {"status":"error","message":"You must be logged in to do that!"} as the response (I have verified this in the browser using firebug). However, in my tests get a 302 response code rather than a 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

The first example included here is successful (assigns[:talk] does not get assigned), but the second is not:

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)>'

I'm not sure exactly what's going on. Is there a way I can test for the actual response code returned to the browser? Or a better way I can test the authorization?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

-柠檬树下少年和吉他 2024-12-15 14:04:25

事实证明,我的项目使用以下函数从 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 建议我检查我的测试日志,因为这揭示了请求的差异。

As it turned out, my project rescued authorization exceptions from CanCan with the following function. Because the function only raises a 401 when the request is ajax (and redirects otherwise), I was getting a 401 in the browser, but not my tests.

# 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

Thanks to zetetic for suggesting I check my test logs, as this revealed the difference in requests.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文