我在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"
块无济于事。我需要在多个控制器和动作之间执行此检查,因此似乎一个共享的示例可能是重用代码的正确方法。 最佳答案
这里的问题是在示例之外调用了记忆的let帮助器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