概要
RSpec の be
マッチャーは何となく雰囲気で、いわゆる「参照一致」だと思っており、そうなら何故別変数のように見える 1
と 1
が一致するのかというのが不思議でした。
理由
be
は equal?
を使って検証するものである。
Ref)
https://relishapp.com/rspec/rspec-expectations/v/3-5/docs/built-in-matchers/equality-matchers
expect(a).to be(b) # passes if a.equal?(b)
#equal?
とは Object#equal? のことであり、以下の動作をする
お互いのObject#object_idが一致する かどうかを調べます。
アクティブなオブジェクト間で 重複しない整数(object_id)が各オブジェクトにひとつずつ割り当てられています。
とのことだが、例外として、
TrueClass, FalseClass, NilClass, Symbol, Fixnum クラス のインスタンスなど Immutable(変更不可)なオブジェクトの一部は同じ内容ならば必ず同じ object_id になります。
とのことだった。
だから expect(1).to be 1
は同じ object_id
を比較でき、成立する。
なお、そもそも expect(1).to be 1
は誤りなので
expect(1).to eq 1
と書くべきである。
同値が同object_idを持つのは、例外的な動作だから。
残った疑問
Immutable(変更不可)なオブジェクト
という文は、.frozen?
が true
という意味と一緒なのだろうか?