Rspec let scoping

let() is supposed to be scoped to the example blocks and unusable elsewhere. You don’t actually use let() as parameters. The reason it does not work with it_behaves_like as a parameter has to do with how let() gets defined. Each example group in Rspec defines a custom class. let() defines an instance method in that class. However, when you call it_behaves_like in that custom class, it is calling at the class level rather than from within an instance.

I’ve used let() like this:

shared_examples_for 'any connection' do
  it 'should have valid connection' do
    connection.valid?
  end
end

describe Connection do
  let(:connection) { Connection.new(settings) }
  let(:settings) { { :blah => :foo } }
  it_behaves_like 'any connection'
end

I’ve done something similar to bcobb’s answer, though I rarely use shared_examples:

module SpecHelpers
  module Connection
    extend ActiveSupport::Concern

    included do
      let(:connection) { raise "You must override 'connection'" }
    end

    module ClassMethods
      def expects_valid_connection
        it "should be a valid connection" do
          connection.should be_valid
        end
      end
    end
  end
end

describe Connection do
  include SpecHelpers::Connection

  let(:connection) { Connection.new }

  expects_valid_connection
end

The definition of those shared examples are more verbose than using shared examples. I guess I find “it_behave_like” being more awkward than extending Rspec directly.

Obviously, you can add arguments to .expects_valid_connections

I wrote this to help a friend’s rspec class: http://ruby-lambda.blogspot.com/2011/02/agile-rspec-with-let.html …

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)