Read more

Using RSpec's late resolving of "let" variables for cleaner specs

Arne Hartherz
June 20, 2011Software engineer at makandra GmbH

Consider the following:

describe '#something' do
  context 'with lots of required arguments' do
    it 'should work' do
      subject.something(:foo => 'foo', :bar => 'bar', :baz => 'baz').should == 'Hello world'
    end

    it 'should work again' do
      subject.stub :target => 'universe'
      subject.something(:foo => 'foo', :bar => 'bar', :baz => 'baz').should == 'Hello universe'
    end

    it 'should work yet again' do
      subject.stub :target => 'multiverse'
      subject.something(:foo => 'foo', :bar => 'bar', :baz => 'baz').should == 'Hello multiverse'
    end
  end
end
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

Something like that gets ugly and/or annoying once you require more than just a simple method call, e.g. with many arguments that are required for a method for some reason.

This cleans up your spec, making it easier to see the requirements at a first glance:

describe '#something' do
  context 'with lots of required arguments' do
    let(:result) { subject.something(:foo => 'foo', :bar => 'bar', :baz => 'baz') }

    it 'should work' do
      result.should == 'Hello world'
    end

    it 'should work again' do
      subject.stub :target => 'universe'
      result.should == 'Hello universe'
    end

    it 'should work yet again' do
      subject.stub :target => 'multiverse'
      result.should == 'Hello multiverse'
    end
  end
end

The reason why this works is because RSpec will evaluate the block assigned for the let call only when result is actually called. This way you can manipulate objects or other data before using the short-hand reference to your method call.

Yes, it is quite similar to using variables introduced via let in before blocks.

Posted by Arne Hartherz to makandra dev (2011-06-20 13:16)