2016-10-09 44 views
2

我在使用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"塊無濟於事。我需要跨多個控制器和動作執行此檢查,因此似乎共享示例可能是重用代碼的正確方法。

回答

3

這裏的問題是在示例之外調用memoized let helper show_params

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 

這是一個非常強大的模式,讓您使用一個約定優於配置的做法,因爲:

不是傳遞的則params的,你可以簡單地從外部範圍,其中要包括的例子引用letlast 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 
+0

這工作很好!非常感謝你!我將共享示例放在一個單獨的文件中('spec/controllers/shared_examples/authorized_action.rb'),在我的'spec/rails_helper.rb'中需要該目錄,然後按照您的建議使用它! – Alexander