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_attributesis not available on an example group (e.g. adescribeorcontextblock). It is only available from within individual examples (e.g.itblocks) or from constructs that run in the scope of an example (e.g.before,let, etc).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With