環境 | |
---|---|
Rails | 6.0.0 |
RSpec | 3.9 |
factory_bot | 5.1.1 |
自分がプチハマりしたので備忘録も兼ねて。
RSpecを書いているとよく見る以下のようなコード。
before do
@user = create(:user)
end
let(:user) { create(:user) }
この2つはほぼ同じ事をしています。
factoryファイルを元にDBにユーザ情報を作成、前者は@user、後者はuserという変数に代入をします。
ここだけ見ていると、letを使った方が1行で書けるし、letだけ使っていれば問題なさそうな気もします。
しかし注意しなければいけないことがあります。
以下のように、代入した変数を使わずにActive Recordにアクセスする場合、letだとエラーが発生します。
User.find 1
=> ActiveRecord::RecordNotFound: Couldn't find User with 'id'=1
これは、letが遅延評価される(代入した変数が参照されたタイミングで評価される)ために起こります。
User.find user.id
ならエラーになりません。
遅延評価されたくない場合はletが使えないのかというと、そういうわけではありません。
遅延評価をしないlet!が用意されています。
let!(:user) { create(:user) }
とすれば、テストを行う前(before doと同じタイミング)に実行されます。
遅延評価にも、必要のない時まで処理をしなくてすむといったメリットがありますので、適切な方を選べるようにしたいですね。