Help us understand the problem. What is going on with this article?

RSpecのletでcreateした時に気をつけること 〜遅延評価〜

環境
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と同じタイミング)に実行されます。

遅延評価にも、必要のない時まで処理をしなくてすむといったメリットがありますので、適切な方を選べるようにしたいですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした