简体   繁体   中英

Passing an example from “it” block to “let” block in RSpec

I was watching a codeschool screencast on using RSpec and it had the following lines:

describe Game do
  describe '#call' do
    let(:description) do |example|
      example.description
    end

    context 'when the choices are different' do

      subject(:game) { described_class.new }
      it 'rock beats scissors' do |example|
        expect(subject.call('rock', 'scissors')).to eq(description)
      end
    end
  end
end

I don't quite see how example argument gets into the 'let' block? Is that a Ruby thing or RSpec magic? Thanks.

See this line in the rspec-core source:

# Simplified version of the code:
def let(name, &block)
  # ...
  if block.arity == 1
    define_method(name) { super(RSpec.current_example, &nil) }
  # ...
end

Because let is re-evaluated for each test, it can be re-defined to include knowledge of the current test context.

Also worth noting is that RSpec.current_example is thread-safe :

def self.current_example
  RSpec::Support.thread_local_data[:current_example]
end

This means even if you are running parallel tests, each let block will always be able to re-evaluate the current example correctly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM