用rspec测试控制器认证的实用方法

时间:2017-11-22 10:12:39

标签: ruby-on-rails rspec devise

我想知道是否有更好的方法来编写控制器请求规范,而不是我目前的工作方式。我使用devise 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

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

2 个答案:

答案 0 :(得分:4)

@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

答案 1 :(得分:0)

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

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"