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

RSpec の letとlet!とbeforeの挙動と実行される順番

More than 1 year has passed since last update.

let と let! の違いは何となく理解していたが、
let! と before の実行順まで把握していなかったので、
この機会に備忘録的にそれぞれをまとめてみました。

let

let は 最初にメソッドが呼ばれた時 に評価されます。

なので例えば
User が複数の Article を持つ場合

◯◯_spec.rb
describe 'let' do
  let(:user) { create(:user) }
  let(:user_article) { create(:article, user_id: user.id) }

  specify 'User が Article を持っていること' do
    expect(user.articles.first).to eq user_article
  end
end

とやるとテストが通らない。。。はず。(面倒臭くて実際にはこのコード書いてない。すみません。)

この場合、

let(:user_article) { create(:article, user_id: user.id) }

が呼ばれるのは

expect(user.articles.first).to eq user_article

の中で "user_article" が呼ばれた時で

"user.articles.first" が処理される時にはまだ実行されていないので "user.articles.first" は空となりテストは通りません。

let!

let! は letが遅延評価であるのとは違い、各サンプルが実行される前に評価されます。
つまり各 it とか specify が実行される直前に評価されるので

先程のテストコードは

◯◯_spec.rb
describe 'let' do
  let!(:user) { create(:user) }
  let!(:user_article) { create(:article, user_id: user.id) }

  specify 'User が Article を持っていること' do
    expect(user.articles.first).to eq user_article
  end
end

このように let を let! に置き換えると specify のブロックが実行される前に

let!(:user)
let!(:user_article)

の両方が処理されるのでテストが通るようになります。

before、before(:each)

let! と同じ。
"before(:each)" と "before(:all)" の違いなどは今は書いていないので
別の記事あたりを参考にしていただければと

それぞれの実行される順番

let と let! は先程述べたタイミングで処理されるので
それぞれの定義の順番は関係ありません。

let! と before の実行タイミングは同時なので、
定義の順番通りに実行されます。

下記のコードの場合

◯◯_spec.rb
before { create(:user) }
let!(:user_article) { create(:article, user_id: user.id) }
before { create(:user_2) }

上から順に処理が行われていく(サンプルコード悪くてすみません。)

さいごに

まだまだわかったようで理解しきれていない部分もあると思うので、
またわかることあれば追記していきたいと思います。

また、不備等あれば教えていただければ幸いです。

hirotakasasaki
マイブームはサーフィン、コーヒースタンド。ご一緒できる方ぜひに。
favy
デジタルマーケティングのスペシャリストと飲食業界出身の食のスペシャリストでチームは構成されていて、飲食市場に特化したマーケティング支援を軸に「飲食店がかんたんに潰れない世界を創る」を真剣に実現するためにチャレンジしています。
http://www.favy.jp/
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