【问题标题】:Practical way to test controller authentication with rspec使用 rspec 测试控制器身份验证的实用方法
【发布时间】:2017-11-22 10:12:38
【问题描述】:

我想知道是否有比我目前更好的方法来编写控制器请求规范。我正在使用设计 gem 进行身份验证。这就是我测试管理控制器的方式:

  describe "#index" do
    context "when not logged in" do
      it "redirects to root page" do
        get admin_index_path

        expect(response).to redirect_to root_path
      end
    end

    context "when logged in as an user" do
      before { sign_in user }

      it "redirects to root page" do
        get admin_index_path

        expect(response).to redirect_to root_path
      end
    end

    context "when logged in as an admin" do
      before { sign_in admin }

      it "opens the page" do
        get admin_index_path
        expect(response).to be_success
      end
    end
  end

如您所见,有一些“样板”代码在我的许多控制器上重复出现。对于需要用户登录的控制器,我必须为每个控制器操作编写“未登录”规范。你怎么做到这一点?有没有办法缩短/共享规范之间的代码?唯一改变的是路径。

【问题讨论】:

标签: ruby-on-rails rspec devise


【解决方案1】:

@Linus 这里是你答案的重构版本

shared_examples "requires login" do |path, user_type|
  context "when not logged in" do
    it "redirects to root path" do
      get public_send("#{path}_path")

      expect(response).to redirect_to root_path
    end
  end

  context "as an #{user_type}" do
    it "redirects to root path" do
      sign_in create(user_type)

      get public_send("#{path}_path")

      expect(response).to redirect_to root_path
    end
  end
end

并像使用它一样

it_behaves_like "requires login", "admin_index", :user 用户

it_behaves_like "requires login", "admin_index", :admin 用于管理员

【讨论】:

  • 将用户类型作为符号传递是个好主意,就像工厂机器人需要它一样。谢谢!
  • 如何传递带有对象的路径?示例:edit_course_path(course)
  • edit_course_path(course) 返回字符串,您可以将其作为参数传递,例如 it_behaves_like "requires login", edit_course_path(course), :admin
  • 但是我只能在it 块中写edit_course_path(course),对吧?
  • 我没听懂你@Linus。你能补充更多细节吗?
【解决方案2】:

好的,我想出了这个解决方案。如果您有更好的想法,请告诉我。

shared_examples "requires user login" do |path|
  context "when not logged in" do
    it "redirects to root path" do
      get public_send(path)

      expect(response).to redirect_to root_path
    end
  end

  context "as an user" do
    it "redirects to root path" do
      sign_in create(:user)

      get public_send(path)

      expect(response).to redirect_to root_path
    end
  end
end

shared_examples "requires admin login" do |path|
  context "as an user" do
    it "redirects to root path" do
      sign_in create(:user)

      get public_send(path)

      expect(response).to redirect_to root_path
    end
  end

  context "as an admin" do
    it "gets 200" do
      sign_in create(:admin)

      get public_send(path)

      expect(response).to be_success
    end
  end
end

使用它们:

it_behaves_like "requires user login", "admin_index_path"

it_behaves_like "requires admin login", "admin_index_path"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多