Reputation: 4774
I have a shared example in RSpec, which tests SMS sending. In my app I have few methods which send an SMS, so I'd like to parametrize the code I test, so that I can use my shared example for all my methods. The only way to do that which I discovered is using eval
function:
RSpec.shared_examples "sending an sms" do |action_code|
it "sends an sms" do
eval(action_code)
expect(WebMock).to have_requested(**my_request**).with(**my_body**)
end
end
So I can use this example like that:
it_behaves_like "sending an sms",
"post :accept, params: { id: reservation.id }"
it_behaves_like "sending an sms",
"post :create, params: reservation_attributes"
How can I achieve this without using eval
function? I tried to use the pattern with yield
command, but it doesn't work because of scope:
Failure/Error: post :create, params: reservation_attributes
reservation_attributes
is not available on an example group (e.g. adescribe
orcontext
block). It is only available from within individual examples (e.g.it
blocks) or from constructs that run in the scope of an example (e.g.before
,let
, etc).
Upvotes: 4
Views: 2669
Reputation: 15045
Actually in your case, action and params can be passed as arguments into shared examples:
RSpec.shared_examples "sending an sms" do |action, params|
it "sends an sms" do
post action, params: params
expect(WebMock).to have_requested(**my_request**).with(**my_body**)
end
end
And called as:
it_behaves_like "sending an sms", :accept, { id: reservation.id }
it_behaves_like "sending an sms", :create, reservation_attributes
Or you can define separate action for every block
RSpec.shared_examples "sending an sms" do
it "sends an sms" do
action
expect(WebMock).to have_requested(**my_request**).with(**my_body**)
end
end
it_behaves_like "sending an sms" do
let(:action) { post :accept, params: { id: reservation.id } }
end
it_behaves_like "sending an sms" do
let(:action) { post :create, params: reservation_attributes }
end
Upvotes: 5