rspecのletで定義した変数をbeforeで変更しても、思ったようには行かないよという話です。
akiyah_spec.rb
# frozen_string_literal: true
require "rails_helper"
describe "Akiyah" do
let(:int) { 123 }
let(:str) { "abc" }
let(:arr) { ["a", "b", "c"] }
before do
int = 456
str = "def"
arr[0] = "x"
arr = ["d", "e", "f"]
arr[1] = "y"
end
it { expect(int).to eq 123 }
it { expect(str).to eq "abc" }
it { expect(arr).to eq ["x", "b", "c"] }
end
letで宣言した変数をbefore内で=で代入しても、itの中では変わっていません。
beforeの中で(あとで使えない)新しい別の変数を作っているだけなんですね。
Array(やHash)の場合に、その中の要素を置き換えている場合は、itの中でも反映されます。
意外にこういう状況にはならないので、あんまり問題にはならないのですが、この前モブプロしているときに遭遇したので書いておきました。
コメントで解説していただいたので追記
letで定義しているのは変数ではなくてメソッドなのだと理解すれば、上のようなコードをみても誤解は減りそうです。
変数
みたいに見えるものを メソッド
の呼び出しだとわかるように変えてみました。
akiyah_spec.rb
# frozen_string_literal: true
require "rails_helper"
describe "Akiyah" do
let(:int) { 123 }
let(:str) { "abc" }
let(:arr) { ["a", "b", "c"] }
before do
int = 456
str = "def"
arr()[0] = "x"
arr = ["d", "e", "f"]
arr[1] = "y"
p arr #=> ["d", "y", "f"]
end
it { expect(int()).to eq 123 }
it { expect(str()).to eq "abc" }
it { expect(arr()).to eq ["x", "b", "c"] }
end
beforeで arr()[0] = "x"
をすると、 arr()
の結果が変更されるのは面白いですね。コメントで書いていただいたように、letで定義したメソッドは戻り値を保存しておくからこうなるのですね。