コード日進月歩

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

RSpecのletは遅延評価なので2つ書いた場合は最も近いブロックの値を評価する

『遅延評価』を謳っているが、重複表記の場合はどうなるのというメモ。 後述しているが 単純に読みにくくなるので使わないことに越したことはない ものです。

環境

$ bundle exec rspec -v
RSpec 3.8
  - rspec-core 3.8.0
  - rspec-expectations 3.8.2
  - rspec-mocks 3.8.0
  - rspec-rails 3.8.1
  - rspec-support 3.8.0

Userモデルを使うとこんな感じで後続のブロックのletが優先される

# == Schema Information
#
# Table name: users
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

require 'rails_helper'

RSpec.describe User, type: :model do

  describe "#create" do
    let(:user) {User.create(name: nil)}

    it "nameはnil" do
      expect(user.name).to eq(nil)
    end

    context "やっぱuserの名前はtaroの時" do
      let(:user) {User.create(name: "taro")}

      it "nameはtaro" do
        expect(user.name).to eq("taro")
      end
    end
  end
end

注意点

遅延評価なので当たり前といえば当たり前ですが、同一のブロックに書かれると後に書かれたほうが勝つ、というような動きはしないので注意。

  describe "#create" do
    let(:user) {User.create(name: nil)}
    it "nameはnil" do
      expect(user.name).to eq(nil)
    end

    let(:user) {User.create(name: "taro")}
    context "やっぱuserの名前はtaroの時" do
      it "nameはtaro" do
        expect(user.name).to eq("taro")
      end
    end
  end

こう書き換えると

$ bundle exec rspec spec/models/user_spec.rb 
F.

Failures:

  1) User#create nameはnil
     Failure/Error: expect(user.name).to eq(nil)
     
       expected: nil
            got: "taro"
     
       (compared using ==)
     # ./spec/models/user_spec.rb:19:in `block (3 levels) in <top (required)>'

あとに書き足したほうが無視される。

このように、単純に読みにくくなるので使わないことに越したことはない

参考リンク