RSpec's let
allows you to super
into "outside" definitions, in parent contexts.
Example:
describe '#save' do
subject { described_class.new(attributes) }
let(:attributes) { title: 'Example', user: create(:user) }
it 'saves' do
expect(subject.save).to eq(true)
end
context 'when trying to set a disallowed title' do
let(:attributes) { super().merge(title: 'Hello') } # <==
it 'will not save' do
expect(subject.save).to eq(false)
end
end
end
I suggest you don't make a habit of using this regularly, as it has high potential to make your tests hard to read and understand.
You're often better of by using factories, generally different implementation patterns, or just duplicating some of your tests' code.
In some situations this has benefits, like making complex setups simpler if you want to modify only one aspect.
My use case for this was testing data migration logic where some edge cases caused different behavior for otherwise fine data. YMMV.
Note that you must use super()
with explicitly no arguments instead of super
. This is because let
defines methods via define_method
(which does not support super
with implicit arguments).