Read more

RSpec: You can super into parent "let" definitions

Arne Hartherz
February 02, 2022Software engineer at makandra GmbH

RSpec's let allows you to super into "outside" definitions, in parent contexts.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

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).

Posted by Arne Hartherz to makandra dev (2022-02-02 09:26)