コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

RSpecのsubjectは同一ブロック内で2回指定しても再実行されるわけではない

2回実行した時…みたいので subjectを2回実行すればいいやん! みたいに思うがそうは問屋が…的な。原理までは調べてないが挙動としてはこうなんだよメモ

環境

$ bundle exec rspec --version
RSpec 3.7
  - rspec-core 3.7.1
  - rspec-expectations 3.7.0
  - rspec-mocks 3.7.0
  - rspec-rails 3.7.2
  - rspec-support 3.7.1

結果

下記のようなクラスで

class Calculate
  def initialize
    @value = 0
  end

  def add_and_print
    @value += 1
  end
end

下記のようなrspecを用意した場合

describe ".add_and_print" do
  let(:obj) { Calculate.new }
  subject { obj.add_and_print }
  context "2回実行した場合" do
    it "1回目は1,2回目は2" do
      expect(subject).to eq(1)
      expect(subject).to eq(2)
    end
  end
end

下記のように失敗する。

Failures:

  1) .add_and_print 2回実行した場合 1回目は1,2回目は2
     Failure/Error: expect(subject).to eq(2)
     
       expected: 2
            got: 1
     
       (compared using ==)

なので意図通りにやりたいときは直実行するのみ

describe ".add_and_print" do
  let(:obj) { Calculate.new }
  context "2回実行した場合" do
    it "1回目は1,2回目は2" do
      expect(obj.add_and_print).to eq(1)
      expect(obj.add_and_print).to eq(2)
    end
  end
end