RSpec不能在共享示例中使用定义的变量

时间:2016-10-09 19:19:25

标签: ruby-on-rails testing rspec

我在为RSpec中的共享示例使用已定义的变量时遇到问题。这是我的考试:

RSpec.shared_examples "check user logged in" do |method, action, params|
  it "redirects to the sign in page if the user is not logged in" do
    send(method, action, params)
    expect(response).to redirect_to(signin_url)
  end
end

RSpec.describe UsersController, type: :controller do
  describe "GET #show" do
    let(:user) { FactoryGirl.create(:user) } 
    let!(:show_params) do 
      return { id: user.id }
    end

    context "navigation" do
      include_examples "check user logged in", :get, :show, show_params
    end
  end
end

在测试中,我检查以确保用户需要在执行操作之前登录。我收到以下错误消息:

  

method_missing':show_params在示例组

上不可用

我需要更改哪些内容才能使show_params可访问?我尝试过使用it_behaves_like代替include_examples而没有运气。我也尝试删除context "navigation"阻止无效。我需要跨多个控制器和操作执行此检查,因此似乎共享示例可能是重用代码的正确方法。

1 个答案:

答案 0 :(得分:3)

这里的问题是memoized let helper show_params在示例之外被调用。

您可以简单地从包含示例的外部范围引用let,而不是传递参数:

RSpec.describe UsersController, type: :controller do
  let(:user) { FactoryGirl.create(:user) }
  describe "GET #show" do
    let(:action) { get :show, id: user }
    it_should_behave_like "an authorized action"
  end
end

RSpec.shared_examples "an authorized action" do
  it "denies access" do
    action
    expect(response).to redirect_to(signin_url) 
  end
end

这是一个非常强大的模式,允许您使用约定优于配置方法,因为last let always wins

RSpec.describe UsersController, type: :controller do
  let(:user) { FactoryGirl.create(:user) }
  describe "GET #show" do
    let(:action) { get :show, id: user }
    it_should_behave_like "an authorized action"

    context "when signed in" do
      before { sign_in user }
      let(:action) { get :show, id: other_user }
      context 'when viewing another user' do
        it_should_behave_like "an authorized action"
      end
    end
  end
end