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 UI/UX Design

UI/UX Design by makandra brand

We make sure that your target audience has the best possible experience with your digital product. You get:

  • Design tailored to your audience
  • Proven processes customized to your needs
  • An expert team of experienced designers
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)