Hung
Hung

Reputation: 519

how subject work in rspec in ruby on rails

I recently learn about rspec test in rails and as following the link https://relishapp.com/rspec/rspec-core/v/3-6/docs/subject/explicit-subject that said "The subject is memoized within an example but not across examples " with the code below:

RSpec.describe Array do
  # This uses a context local variable. As you can see from the
  # specs, it can mutate across examples. Use with caution.
  element_list = [1, 2, 3]

  subject { element_list.pop }

  it "is memoized across calls (i.e. the block is invoked once)" do
    expect {
      3.times { subject }
    }.to change{ element_list }.from([1, 2, 3]).to([1, 2])
    expect(subject).to eq(3)
  end

  it "is not memoized across examples" do
    expect{ subject }.to change{ element_list }.from([1, 2]).to([1])
    expect(subject).to eq(2)
  end
end

Can anyone explain to me:

Thank you.

Upvotes: 1

Views: 4107

Answers (1)

moveson
moveson

Reputation: 5213

First, by way of clarification, the RSpec subject helper is nothing more than a special case of RSpec's let helper. Using subject { element_list.pop } is equivalent to let(:subject) { element_list.pop }.

Like any other let, subject is evaluated once per example. If subject has a value, that value is returned without re-evaluation. The general term for this is "memoization."

Ruby's ||= operator does the same thing. It says, "if a value exists in that variable, return the value, otherwise evaluate the expression, assign it to the variable, and return the value." You can see this concept in action in the console with this example:

>> element_list = [1, 2, 3]
>> subject ||= element_list.pop
=> 3
>> element_list
=> [1, 2]
>> subject ||= element_list.pop
=> 3
>> element_list
=> [1, 2]
>> subject
=> 3

The fact that subject is not memoized across examples means that its value is reset when a new example is executed. So for your next it block, subject will start out unassigned and its expression will be re-evaluated when it is first used in that next it block.

Upvotes: 2

Related Questions