Ruby on rails 用rspec测试控制器身份验证的实用方法

Ruby on rails 用rspec测试控制器身份验证的实用方法,ruby-on-rails,rspec,devise,Ruby On Rails,Rspec,Devise,我想知道是否有比我现在做的更好的方法来编写控制器请求规范。我正在使用Desive 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

我想知道是否有比我现在做的更好的方法来编写控制器请求规范。我正在使用Desive 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

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

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

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"


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

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"


@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
像这样使用它

它的行为类似于用户的“需要登录”、“管理索引”、:user


它的行为类似于“需要登录”、“管理员索引”:admin
for admin

@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
像这样使用它

它的行为类似于用户的“需要登录”、“管理索引”、:user


it\u的行为类似于“需要登录”,“admin\u索引”,“admin
for admin

Replace
it\u的行为类似于
包含示例
为什么一个替代另一个替代
it\u的行为类似于
包含示例
为什么一个替代另一个好主意将用户类型作为符号传递,就像工厂机器人需要它一样。谢谢如何传递带有对象的路径?示例:
edit\u course\u path(course)
edit\u course\u path(course)
返回可以作为参数传递的字符串,如
它的行为类似于“需要登录”,“edit\u course\u path(course)”:admin
但我只能在
it
块中编写
edit\u course\u path(course)
,对吗?我没有完全理解@Linus。你能添加更多细节吗?把用户类型作为符号传递是个好主意,就像工厂机器人需要它一样。谢谢如何传递带有对象的路径?示例:
edit\u course\u path(course)
edit\u course\u path(course)
返回可以作为参数传递的字符串,如
它的行为类似于“需要登录”,“edit\u course\u path(course)”:admin
但我只能在
it
块中编写
edit\u course\u path(course)
,对吗?我没有完全理解@Linus。你能补充更多细节吗?