Problem:
I am attempting to create a shared example that has a series of base tests and conditionally can run a few more tests if a let was declared in the block.
Background:
I have a response object that is used as the return value for service objects. It has a payload, which by default is an empty hash but it can contain data if the service sets them.
Using a shared example, I can easily cover the base case when a payload is not present. However, some services populate the payload. Given that the payload often references variables defined by let statements, I opted to share the context through a block instead of passing in parameters to the shared context.
Here is what I would like to do, I have mimicked the behavior with doubles so that this snippet is valid and can be used to test. The subject double represents the service object, and execute returns a double representing the response object.
RSpec.describe 'conditional shared_examples' do
shared_examples_for 'a successful Service' do
let(:response) { subject.execute }
it 'returns a success ServiceResponse' do
expect(response.success?).to be(true)
end
it 'contains the payload from the service', if: payload do
expect(response.payload).to eq(payload)
end
end
describe 'base shared_examples without a block' do
subject { double(execute: double(success?: true)) }
it_behaves_like 'a successful Service'
end
describe 'when a block is provided' do
subject { double(execute: double(success?: true, payload: { foo: 'bar' })) }
it_behaves_like 'a successful Service' do
let(:payload) { { foo: 'bar' } }
end
end
end
This fails because payload is not available for the conditional check, here is the error:
NameError:
undefined local variable or method `payload'
This makes sense to me, payload is not available at the ExampleGroup level, it is only available from within an example.
Questions:
Is there a way to check if a block was passed or if a method has been defined through let at the ExampleGroup level?
How can I conditionally check if this it_behaves_like was passed a block or has a specific let method declared?